Board Game Arena
tournoidoc139_ko
http:///%EB%8C%80%EB%AC%B8
MediaWiki 1.39.0
first-letter
미디어
특수
토론
사용자
사용자토론
Board Game Arena
Board Game Arena토론
파일
파일토론
미디어위키
미디어위키토론
틀
틀토론
도움말
도움말토론
분류
분류토론
Main Page
0
1
1
2012-01-05T15:36:33Z
MediaWiki default
0
wikitext
text/x-wiki
'''MediaWiki has been successfully installed.'''
Consult the [//meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software.
== Getting started ==
* [//www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list]
* [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ]
* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]
b7a3846f2c55072191227d89a3204fe379288fee
6
1
2012-01-23T08:20:44Z
Sourisdudesert
1
Redirected page to [[Help]]
wikitext
text/x-wiki
#REDIRECT [[Help]]
716110d80c64acdd324d04dd290c1bffae7bce06
미디어위키:Sidebar
8
2
2
2012-01-06T14:15:59Z
Sourisdudesert
1
Created page with " * navigation ** http://boardgamearena.com|BoardGameArena.com ** mainpage|mainpage-description ** recentchanges-url|recentchanges * SEARCH * TOOLBOX * LANGUAGES"
wikitext
text/x-wiki
* navigation
** http://boardgamearena.com|BoardGameArena.com
** mainpage|mainpage-description
** recentchanges-url|recentchanges
* SEARCH
* TOOLBOX
* LANGUAGES
bd8432e95416d227d9bca445c1f77a70aee1fbec
Faq
0
3
3
2012-01-20T20:48:59Z
Sourisdudesert
1
Created page with " test [[File:Reputation_down.png]]"
wikitext
text/x-wiki
test
[[File:Reputation_down.png]]
7b93a95fc5cc35ff8637c12da14176e1205f1e01
4
3
2012-01-20T21:10:48Z
Sourisdudesert
1
wikitext
text/x-wiki
test
[[File:Reputation_down.png]]
http://en.wikipedia.org/upload/b/bc/Wiki.png
9195da8cff4846394bfa49361b55be1597869f51
5
4
2012-01-20T21:11:12Z
Sourisdudesert
1
wikitext
text/x-wiki
test
[[File:Reputation_down.png]]
http://en.wikipedia.org/upload/b/bc/Wiki.png
http://static.tournoi-en-ligne.fr/data/themereleases/120120-1440/img/stoneage/game_icon.png
92692e80e27e413417c9e34326c6e0df02a4ba1c
8
5
2012-01-23T08:25:52Z
Sourisdudesert
1
wikitext
text/x-wiki
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the bug section in the forum, see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
What is the legal status of this website?
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
I'm a game publisher: why would I like to have my game on Board Game Arena?
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
Meeting players and starting games
I launched a new table but nobody is joining?
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
I joined a game. When does the game start?
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game.
What is the meaning of the small color circle next to players names?
: this player is active. He completed an action very recently.
: this player is inactive. He is connected to the website but did not perform any action recently.
: this player is offline.
During the game
What is the meaning of the icons next to players names?
: this player must make a move now.
: this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
: this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
: this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
A player has to make a move but he/she doesn't. What can I do?
First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
Then you can ask this player to confirm that he is still thinking about how to play.
If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
What is the current progression of the game I'm playing?
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
What is forbidden on Board Game Arena?
Leaving a game in progress on purpose.
Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation.
Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
Running out of time on the game clock.
Giving some piece of information about the current game situation that corrupts the normal game flow.
Communicating with another player about the game privately (ex: with MSN).
Provocation / triumphalism / defeatism ... anything which is not fair play.
Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
What is absolutely forbidden in Board Game Arena?
Creating multiple account and playing against oneself.
Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
What if some player does something wrong?
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
ab1d2e0d199f098d3288fe43081e422ab59e699c
9
8
2012-01-23T08:28:22Z
Sourisdudesert
1
wikitext
text/x-wiki
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game.
===What is the meaning of the small color circle next to players names?===
: this player is active. He completed an action very recently.
: this player is inactive. He is connected to the website but did not perform any action recently.
: this player is offline.
== During the game ==
===What is the meaning of the icons next to players names?===
: this player must make a move now.
: this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
: this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
: this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
556e32db4b9111710ffcbc1ad05f9ec857794e31
10
9
2012-01-23T08:29:03Z
Sourisdudesert
1
/* What is the meaning of the small color circle next to players names? */
wikitext
text/x-wiki
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
== During the game ==
===What is the meaning of the icons next to players names?===
: this player must make a move now.
: this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
: this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
: this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
c6e6418ab580cd5812c4f613e1be5737fa3a6f7c
11
10
2012-01-23T08:29:43Z
Sourisdudesert
1
/* What is the meaning of the icons next to players names? */
wikitext
text/x-wiki
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
3678e480ae646ee50cada05e6bf34cac1faf094c
24
11
2012-01-23T08:43:03Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
929b9aebaa71e05b8e961016d35d724169bbcf2d
Help
0
4
7
2012-01-23T08:23:35Z
Sourisdudesert
1
Created page with "An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com]] Forums are also helpful to get information. == Hel..."
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com]] Forums are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena]]
** [[About us]]
** [[Club Board Game Arena]]
** [[Contact us]]
=== Detailled help ===
* [[Getting started]]
* [[Referral]]
* [[Browser support]]
* [[Moderation and grades]]
* [[Game clock]]
* [[Rating]]
* [[Reputation]]
* [[Translation guidelines]]
bb066b4658e936f326aa0ee996bb45e23cb8c2b0
12
7
2012-01-23T08:30:09Z
Sourisdudesert
1
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com] Forums are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena]]
** [[About us]]
** [[Club Board Game Arena]]
** [[Contact us]]
=== Detailled help ===
* [[Getting started]]
* [[Referral]]
* [[Browser support]]
* [[Moderation and grades]]
* [[Game clock]]
* [[Rating]]
* [[Reputation]]
* [[Translation guidelines]]
95118ab41bd97e3433383cecebb8e7e133c40b10
13
12
2012-01-23T08:30:21Z
Sourisdudesert
1
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena]]
** [[About us]]
** [[Club Board Game Arena]]
** [[Contact us]]
=== Detailled help ===
* [[Getting started]]
* [[Referral]]
* [[Browser support]]
* [[Moderation and grades]]
* [[Game clock]]
* [[Rating]]
* [[Reputation]]
* [[Translation guidelines]]
16b14d9549ac5aa2e310653b33e55be4abd27bb0
About Board Game Arena
0
5
14
2012-01-23T08:31:22Z
Sourisdudesert
1
Created page with "With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming more simple a..."
wikitext
text/x-wiki
With '''Board Game Arena''' you can play board games online with the whole world.
Board Game Arena is a next generation game platform which makes online gaming more simple and attractive:
* Nothing to install: play straight from your browser, from anywhere, at anytime.
* Real time: your opponents are online, you play "live".
* Simple: if you know the game, then you know how to play online.
* Free.
Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We are specialized in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allow us to propose a '''new game every month'''.
b9d59b3d8e80f8df79151e82dbdede2ee6efc91c
25
14
2012-01-23T08:43:15Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
With '''Board Game Arena''' you can play board games online with the whole world.
Board Game Arena is a next generation game platform which makes online gaming more simple and attractive:
* Nothing to install: play straight from your browser, from anywhere, at anytime.
* Real time: your opponents are online, you play "live".
* Simple: if you know the game, then you know how to play online.
* Free.
Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We are specialized in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allow us to propose a '''new game every month'''.
4f7854886444585b16fecb70e4b46c419e6db368
28
25
2012-01-23T08:43:48Z
Sourisdudesert
1
wikitext
text/x-wiki
With '''Board Game Arena''' you can play board games online with the whole world.
Board Game Arena is a next generation game platform which makes online gaming more simple and attractive:
* Nothing to install: play straight from your browser, from anywhere, at anytime.
* Real time: your opponents are online, you play "live".
* Simple: if you know the game, then you know how to play online.
* Free.
Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We are specialized in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allow us to propose a '''new game every month'''.
b9d59b3d8e80f8df79151e82dbdede2ee6efc91c
About us
0
6
15
2012-01-23T08:31:55Z
Sourisdudesert
1
Created page with "First, we should say that we are gamers. Real, complete boardgames addicts. We designed '''Board Game Arena''' for players who can't play for real because of time, geographic..."
wikitext
text/x-wiki
First, we should say that we are gamers. Real, complete boardgames addicts.
We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games.
Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommand you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle).
[[Contact us]]
09d076571c067045048850f642e222a1e1485eb7
26
15
2012-01-23T08:43:26Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
First, we should say that we are gamers. Real, complete boardgames addicts.
We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games.
Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommand you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle).
[[Contact us]]
366663e98e2fe4f1c5659450c36d0b7db247b03f
27
26
2012-01-23T08:43:39Z
Sourisdudesert
1
wikitext
text/x-wiki
First, we should say that we are gamers. Real, complete boardgames addicts.
We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games.
Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommand you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle).
[[Contact us]]
09d076571c067045048850f642e222a1e1485eb7
Club
0
7
16
2012-01-23T08:32:39Z
Sourisdudesert
1
Redirected page to [[Club Board Game Arena]]
wikitext
text/x-wiki
#REDIRECT [[Club Board Game Arena]]
fac244084d01208926b41fc59a051c6ed0c0748a
Club Board Game Arena
0
8
17
2012-01-23T08:34:49Z
Sourisdudesert
1
Created page with "Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''. A..."
wikitext
text/x-wiki
Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''.
As you can imagine, though, this website needs a lot of time and some money to keep things running smoothly. Some players are helping us with contributions or through donations. This website can exist only because of the help from these players, and to thank them we make them members of the "Board Game Arena Club".
== How can I become a club member ? ==
The three main ways to become a club member are:
* Make this website known (see referral)
* [http://en.boardgamearena.com/#!translationhq Contribute to translate] this website
* Support this website with a donation (payment buttons below)
{|
|Donate '''20€'''
(1 year club membership)
|Donate '''11€'''
(6 months club membership)
|Donate '''4€'''
(2 months club membership)
|-
|{one_year_membership}
|{six_month_membership}
|{two_month_membership}
|}
==Why should I join the club ?==
The main reason you should join the club is to support this website. Also, as a token of appreciation for their support, we give to club members an access to some statistics: ELO ranking of all members including yours (instead of ), games statistics and specific player statistics for each game.
Why can't you just have a standard donation system where I can choose any money amount ?
With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors.
Is it mandatory to join the club ?
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members.
What is a beginner account ?
When you join Board Game Arena, your get a "beginner account" () for 30 days. This beginner account allow you to view your own ELO ranking () for each game. After 30 days, your account becomes a standard non member account ().
What becomes of the money ?
Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
05a49a509de676c255b30cd47a1719a179d3873e
18
17
2012-01-23T08:35:14Z
Sourisdudesert
1
/* How can I become a club member ? */
wikitext
text/x-wiki
Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''.
As you can imagine, though, this website needs a lot of time and some money to keep things running smoothly. Some players are helping us with contributions or through donations. This website can exist only because of the help from these players, and to thank them we make them members of the "Board Game Arena Club".
== How can I become a club member ? ==
The three main ways to become a club member are:
* Make this website known (see [[referral]])
* [http://en.boardgamearena.com/#!translationhq Contribute to translate] this website
* Support this website with a donation (payment buttons below)
{|
|Donate '''20€'''
(1 year club membership)
|Donate '''11€'''
(6 months club membership)
|Donate '''4€'''
(2 months club membership)
|-
|{one_year_membership}
|{six_month_membership}
|{two_month_membership}
|}
==Why should I join the club ?==
The main reason you should join the club is to support this website. Also, as a token of appreciation for their support, we give to club members an access to some statistics: ELO ranking of all members including yours (instead of ), games statistics and specific player statistics for each game.
Why can't you just have a standard donation system where I can choose any money amount ?
With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors.
Is it mandatory to join the club ?
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members.
What is a beginner account ?
When you join Board Game Arena, your get a "beginner account" () for 30 days. This beginner account allow you to view your own ELO ranking () for each game. After 30 days, your account becomes a standard non member account ().
What becomes of the money ?
Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
eb70d022960d5fd26851ae3c461dcf0de7f275f4
19
18
2012-01-23T08:37:03Z
Sourisdudesert
1
wikitext
text/x-wiki
Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''.
As you can imagine, though, this website needs a lot of time and some money to keep things running smoothly. Some players are helping us with contributions or through donations. This website can exist only because of the help from these players, and to thank them we make them members of the "Board Game Arena Club".
== How can I become a club member ? ==
The three main ways to become a club member are:
* Make this website known (see [[referral]])
* [http://en.boardgamearena.com/#!translationhq Contribute to translate] this website
* Support this website with a donation (payment buttons below)
{|
|Donate '''20€'''
(1 year club membership)
|Donate '''11€'''
(6 months club membership)
|Donate '''4€'''
(2 months club membership)
|-
|{one_year_membership}
|{six_month_membership}
|{two_month_membership}
|}
==Why should I join the club ?==
The main reason you should join the club is to support this website. Also, as a token of appreciation for their support, we give to club members an access to some statistics: ELO ranking http://en.boardgamearena.com/theme/img/common/rank.png of all members including yours (instead of http://fr.boardgamearena.com/theme/img/common/rankmask.png), games statistics and specific player statistics for each game.
==Why can't you just have a standard donation system where I can choose any money amount ?==
With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors.
==Is it mandatory to join the club ?==
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members.
==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif ==
When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif).
==What becomes of the money ?==
Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
a12f51dc80f363786676e4551d1473aabc326650
20
19
2012-01-23T08:38:47Z
Sourisdudesert
1
/* Why should I join the club ? */
wikitext
text/x-wiki
Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''.
As you can imagine, though, this website needs a lot of time and some money to keep things running smoothly. Some players are helping us with contributions or through donations. This website can exist only because of the help from these players, and to thank them we make them members of the "Board Game Arena Club".
== How can I become a club member ? ==
The three main ways to become a club member are:
* Make this website known (see [[referral]])
* [http://en.boardgamearena.com/#!translationhq Contribute to translate] this website
* Support this website with a donation (payment buttons below)
{|
|Donate '''20€'''
(1 year club membership)
|Donate '''11€'''
(6 months club membership)
|Donate '''4€'''
(2 months club membership)
|-
|{one_year_membership}
|{six_month_membership}
|{two_month_membership}
|}
==Why should I join the club ?==
The main reason you should join the club is to support this website. Also, as a token of appreciation for their support, we give to club members an access to some statistics: ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) of all members including yours (instead of http://fr.boardgamearena.com/theme/img/common/rankmask.png), games statistics and specific player statistics for each game.
==Why can't you just have a standard donation system where I can choose any money amount ?==
With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors.
==Is it mandatory to join the club ?==
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members.
==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif ==
When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif).
==What becomes of the money ?==
Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
07d7d56ac7137270da1cb1e701810fd74c30b286
Contact us
0
9
21
2012-01-23T08:40:19Z
Sourisdudesert
1
Created page with "'''Board Game Arena''' is located in France. == E-mail contact == contact(at)boardgamearena.com We receive *a lot* of e-mails. Please do not send us an e-mail if: * ... i..."
wikitext
text/x-wiki
'''Board Game Arena''' is located in France.
== E-mail contact ==
contact(at)boardgamearena.com
We receive *a lot* of e-mails. Please do not send us an e-mail if:
* ... if you want to report a bug, please do it in the corresponding forum.
* ... if you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile
== Responsible ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
3fa5849702cf1b1b19bd3acb243c32dbb041a4a9
Getting started
0
10
22
2012-01-23T08:42:02Z
Sourisdudesert
1
Created page with "With '''Board Game Arena''' you can play within a few clicks. By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables wa..."
wikitext
text/x-wiki
With '''Board Game Arena''' you can play within a few clicks.
By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables waiting for players.
You can join a game by clicking on "View table" then "Join game".
If you prefer, you can create a new game table: click on the "Launch table" button that corresponds to the game you want to play, and wait for your opponents.
Important to know before you start:
* It's much better to join a table already created than to create a new one.
* For most popular games you will find opponents at any time. For the others, try to connect around peak hour (around 22h CEST) to maximize your chances.
* When you start a game you can't leave the table until it ends. If you leave you will receive a penalty which cause you difficulties to find opponents later.
00acad1f28c408117fc7c59eac2c4627a71d7e72
23
22
2012-01-23T08:42:52Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
With '''Board Game Arena''' you can play within a few clicks.
By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables waiting for players.
You can join a game by clicking on "View table" then "Join game".
If you prefer, you can create a new game table: click on the "Launch table" button that corresponds to the game you want to play, and wait for your opponents.
Important to know before you start:
* It's much better to join a table already created than to create a new one.
* For most popular games you will find opponents at any time. For the others, try to connect around peak hour (around 22h CEST) to maximize your chances.
* When you start a game you can't leave the table until it ends. If you leave you will receive a penalty which cause you difficulties to find opponents later.
860720b52040414f964590d5eb8639fb21735545
Referral
0
11
29
2012-01-23T08:46:41Z
Sourisdudesert
1
Created page with "[[Category:Help]] When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]] == How does this work? == Each time a new player..."
wikitext
text/x-wiki
[[Category:Help]]
When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]]
== How does this work? ==
Each time a new player create an account on Board Game Arena from you referrer web address (see below), he becomes one of your '''referees'''. As soon as this referee played few games, you become a member of BGA club.
== How to get referees? ==
To recruit referees, use your personal referrer web address:
{sponsorshipurl}
New players MUST create an account from this web address to become one of your referees.
== How to get many referees? ==
* [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook]
* [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter]
* [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email]
* Publish my personal web address in some forum, send it by MSN, ...
== How many BGA club membership days can I win? ==
As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership.
''Note: your account upgrade will be effective within 24 hours.''
As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
... and so on: as your referees number grows you can win many free memberships !
== Referees and multiple account ==
It is of course forbidden to create fake referee accounts to win free memberships.
52e8ab57da4a8638af8bcfdb8ab9549d2bd5ad12
분류:Help
14
12
30
2012-01-23T08:47:01Z
Sourisdudesert
1
Created page with "Board Game Arena help pages"
wikitext
text/x-wiki
Board Game Arena help pages
adc7e25dcb01838e74ee4f7611812cf2762d2767
Browser support
0
13
31
2012-01-23T08:47:52Z
Sourisdudesert
1
Created page with "Board Game Arena is using the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download, no plugin t..."
wikitext
text/x-wiki
Board Game Arena is using the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download, no plugin to install, ...
Consequently, to play you need to use a recent web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be.
We officially support the following browsers:
* Mozilla Firefox 3.5+
* Google Chrome 4+
* Internet Explorer 8 (partial support for IE7)
* Internet Explorer 9
* Safari 4+
(Note: we are NOT supporting iPad or similar tablets)
This website uses Javascript technology and your browser's graphics possibilities intensely. Thus, if you want to have the best game experience with Board Game Arena, you should use one of these browsers:
* Mozilla Firefox 4
* Google Chrome 10
32bb40e75bb29f6d724daafd30c7906adcadadb7
36
31
2012-01-23T08:52:07Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
Board Game Arena is using the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download, no plugin to install, ...
Consequently, to play you need to use a recent web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be.
We officially support the following browsers:
* Mozilla Firefox 3.5+
* Google Chrome 4+
* Internet Explorer 8 (partial support for IE7)
* Internet Explorer 9
* Safari 4+
(Note: we are NOT supporting iPad or similar tablets)
This website uses Javascript technology and your browser's graphics possibilities intensely. Thus, if you want to have the best game experience with Board Game Arena, you should use one of these browsers:
* Mozilla Firefox 4
* Google Chrome 10
03a7ec9371d3e330c0ce5224bdda0f3bf49ec060
Moderation and grades
0
14
32
2012-01-23T08:49:30Z
Sourisdudesert
1
Created page with "Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit o..."
wikitext
text/x-wiki
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a '''mortal'''. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the '''angel''' grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to '''devilkin''' or '''demon'''.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== All grades ==
* '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel).
* '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points.
* '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade.
* '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased.
* '''Archangel''': this is the Board Game Arena administrators' grade.
* '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...)
* '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time.
05df6f50ad4723b2aa3c8dfd1e36e49da6dcb38e
35
32
2012-01-23T08:51:55Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a '''mortal'''. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the '''angel''' grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to '''devilkin''' or '''demon'''.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== All grades ==
* '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel).
* '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points.
* '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade.
* '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased.
* '''Archangel''': this is the Board Game Arena administrators' grade.
* '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...)
* '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time.
49931146459d3900e8e8099ce554da943f7a304b
Game clock
0
15
33
2012-01-23T08:51:23Z
Sourisdudesert
1
Created page with "On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves. Your initial delay at the beginning of a game is most of the time '''3 ..."
wikitext
text/x-wiki
On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves.
Your initial delay at the beginning of a game is most of the time '''3 minutes'''. At each turn, or on specific occasion, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game.
== Time to think ==
Your alloted time to think is displayed on the right of your player's name. When it's your turn to player, this time is also displayed at the top of the web page.
== Game speed ==
Table administrator can make a choice between 4 game speed profile:
* Fast
* Normal
* Slow
* Without time limit
The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing.
Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing.
== Running out of time ==
As soon as you run out of time, you get a clock penalty.
If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ...
== Move time limit ==
In addition to your classical time to think, you have a limited time alloted for each move.
When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you goes over this limit, you become eligible to be expelled from the game.
== "My opponent is too slow" ==
Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his alloted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so.
== "I would like to think a little" ==
If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page.
Thus, your opponents will receive a message and won't be thinking you are away from keyboard.
Clicking on this link is not mandatory, but we encourage its use for courtesy.
1cfe01c7a6e760c91b41e2d84865f9706010ebdf
34
33
2012-01-23T08:51:44Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves.
Your initial delay at the beginning of a game is most of the time '''3 minutes'''. At each turn, or on specific occasion, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game.
== Time to think ==
Your alloted time to think is displayed on the right of your player's name. When it's your turn to player, this time is also displayed at the top of the web page.
== Game speed ==
Table administrator can make a choice between 4 game speed profile:
* Fast
* Normal
* Slow
* Without time limit
The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing.
Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing.
== Running out of time ==
As soon as you run out of time, you get a clock penalty.
If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ...
== Move time limit ==
In addition to your classical time to think, you have a limited time alloted for each move.
When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you goes over this limit, you become eligible to be expelled from the game.
== "My opponent is too slow" ==
Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his alloted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so.
== "I would like to think a little" ==
If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page.
Thus, your opponents will receive a message and won't be thinking you are away from keyboard.
Clicking on this link is not mandatory, but we encourage its use for courtesy.
82143c3b2c0b2426ec6fbc8637e3c739608e6bfb
Rating
0
16
37
2012-01-23T08:53:27Z
Sourisdudesert
1
Created page with " == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign . Example: 1648 http://fr.boardgamearena.com/theme..."
wikitext
text/x-wiki
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign .
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you loose a game.
== How is my ELO ranking computed ? ==
The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
Let's try to make it simple: the points you win/loose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you loose at the same table, your ranking will decrease a little. And so on ...
In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
== Okay, but I want to know the formula ! ==
At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* Table Level (TL) is the average of ELO ratings of all players at this table.
* The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player).
* The performance (P) of a player is TL+S.
* The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
6a46415cd42c733e8f6c21168baf058ec0295e5d
38
37
2012-01-23T08:54:06Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you loose a game.
== How is my ELO ranking computed ? ==
The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
Let's try to make it simple: the points you win/loose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you loose at the same table, your ranking will decrease a little. And so on ...
In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
== Okay, but I want to know the formula ! ==
At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* Table Level (TL) is the average of ELO ratings of all players at this table.
* The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player).
* The performance (P) of a player is TL+S.
* The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
9b83bb61530a3473b4ced7a0e88dac9b3121235a
Reputation
0
17
39
2012-01-23T08:57:12Z
Sourisdudesert
1
Created page with "[[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To a..."
wikitext
text/x-wiki
[[Category:Help]]
== What is reputation ? ==
On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance.
To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items:
* Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png)
* % of games you finished
* % of games you finished with no clock penalties
Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits.
== How to increase my reputation / what makes my reputation decrease ? ==
At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks.
* a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player.
* a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player.
You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change.
As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player.
By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information.
== Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png ==
* Be polite ! Say at least "hello" and "good luck" at the beginning of the game. "good game" ("gg") at the end of the game.
* When you need some time to think, click on "I would like to think a little" link.
* Stay calm in any circumstances: it's a game.
* Don't press your opponent to play if he has some time left.
* If you really can't finish the game (this is not supposed to happened...), then say you are sorry and leave the game by your own to save your opponents time.
* Be a good looser: if your loose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a for this reason!).
* Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation.
== What are the consequences of a bad reputation ? ==
A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you.
It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents.
ccf3fbc039164bc5b2119e80643b725a1e974e87
40
39
2012-01-23T08:57:39Z
Sourisdudesert
1
/* Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png */
wikitext
text/x-wiki
[[Category:Help]]
== What is reputation ? ==
On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance.
To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items:
* Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png)
* % of games you finished
* % of games you finished with no clock penalties
Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits.
== How to increase my reputation / what makes my reputation decrease ? ==
At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks.
* a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player.
* a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player.
You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change.
As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player.
By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information.
== Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png ==
* Be polite ! Say at least "hello" and "good luck" at the beginning of the game. "good game" ("gg") at the end of the game.
* When you need some time to think, click on "I would like to think a little" link.
* Stay calm in any circumstances: it's a game.
* Don't press your opponent to play if he has some time left.
* If you really can't finish the game (this is not supposed to happened...), then say you are sorry and leave the game by your own to save your opponents time.
* Be a good looser: if your loose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!).
* Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation.
== What are the consequences of a bad reputation ? ==
A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you.
It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents.
170ac86366603b161f7deb20712a920f5e460408
Translation guidelines
0
18
41
2012-01-23T08:58:49Z
Sourisdudesert
1
Created page with "The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to ena..."
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated ? ==
Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later...
== Who should translate ? ==
This is important : only native speakers of a given language should translate in this language.
When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronomical rules usual for the gaming audience of their country.
As Board Game Arena's team's mothertongue is french, we will take charge of the french translations.
We will also release the first version of the english translation. As we are not perfect speakers of Shakespeare's language, these translation will be open for review and correction from native english speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the translation forum (in english or in french), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into ? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language.
== I fixed some translations, but they don't appear to have changed on the site ? ==
Translation files are updated each time we do a new release, so you have to wait until the next BGA release for your changes to appear on the site. Usually this should happen every week or two.
== How long will it be possible to change the translations ? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating ? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all!
== Translation tips ==
Use the 'TAB' key to go from one text box to another. This is easier than clicking.
Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
When in doubt, leave a comment for the next translator.
When you fix someone's translation, leave a comment if the reason for the change is not obvious.
When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
f785003cc6caeb1c2fd8407b5ea381eb725dad8b
42
41
2012-01-23T08:59:19Z
Sourisdudesert
1
/* About context */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated ? ==
Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later...
== Who should translate ? ==
This is important : only native speakers of a given language should translate in this language.
When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronomical rules usual for the gaming audience of their country.
As Board Game Arena's team's mothertongue is french, we will take charge of the french translations.
We will also release the first version of the english translation. As we are not perfect speakers of Shakespeare's language, these translation will be open for review and correction from native english speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into ? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language.
== I fixed some translations, but they don't appear to have changed on the site ? ==
Translation files are updated each time we do a new release, so you have to wait until the next BGA release for your changes to appear on the site. Usually this should happen every week or two.
== How long will it be possible to change the translations ? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating ? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all!
== Translation tips ==
Use the 'TAB' key to go from one text box to another. This is easier than clicking.
Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
When in doubt, leave a comment for the next translator.
When you fix someone's translation, leave a comment if the reason for the change is not obvious.
When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
b99f4ae78569524581017328ac85c784a02229ee
43
42
2012-01-23T08:59:44Z
Sourisdudesert
1
/* Translation tips */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated ? ==
Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later...
== Who should translate ? ==
This is important : only native speakers of a given language should translate in this language.
When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronomical rules usual for the gaming audience of their country.
As Board Game Arena's team's mothertongue is french, we will take charge of the french translations.
We will also release the first version of the english translation. As we are not perfect speakers of Shakespeare's language, these translation will be open for review and correction from native english speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into ? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language.
== I fixed some translations, but they don't appear to have changed on the site ? ==
Translation files are updated each time we do a new release, so you have to wait until the next BGA release for your changes to appear on the site. Usually this should happen every week or two.
== How long will it be possible to change the translations ? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating ? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
2ab2b11b7206e323ff840a76b8a125026e1e0344
Translationguidelines
0
19
44
2012-01-23T09:00:27Z
Sourisdudesert
1
Redirected page to [[Translation Guidelines]]
wikitext
text/x-wiki
#REDIRECT [[Translation Guidelines]]
08fc23949a4a226d9c81cccddc96fd7b9f4df0c0
45
44
2012-01-23T09:00:46Z
Sourisdudesert
1
Redirected page to [[Translation guidelines]]
wikitext
text/x-wiki
#REDIRECT [[Translation guidelines]]
9f3b026121a1f6a6e96bb1a66cffcbc391a612e0
미디어위키:Sitenotice
8
20
46
2012-01-23T09:02:55Z
Sourisdudesert
1
Created page with "<div style="font-size: 110%; background-color: ivory; padding: 0.5ex; border: 1px solid black; text-align: center;"> This is a documentation for [http://boardgamearena.com Boa..."
wikitext
text/x-wiki
<div style="font-size: 110%; background-color: ivory; padding: 0.5ex; border: 1px solid black; text-align: center;">
This is a documentation for [http://boardgamearena.com Board Game Arena]: play board games online !
</div>
eb809cbdb9e505f0fa399f3b2ceb6a38ecf4d423
Gamehelpstoneage
0
21
47
2012-01-23T09:11:20Z
Sourisdudesert
1
Created page with " == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, with your civilizat..."
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, with your civilization cards.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players placed their people on "rings" (1 people per ring).
Special rules with 2 players:
* only 1 player in each of the following: forest, clay pit, quarry, and river.
* only 2 of the 3 places: tool maker, hut, and field may be filled in each round.
Special rules with 3 players:
* maximum of 2 players in each of the following: forest, clay pit, quarry, and river.
* only 2 of the 3 places: tool maker, hut, and field may be filled in each round.
===Use the actions of your placed people===
Each player uses all his placed people in any order, and realize the corresponding actions:
* hunting grounds, forest, clay pit, quarry, and river: roll 1 dice per people and take corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* field: increase agriculture level.
* tool: get one tool.
* hut: get one additional people.
* building: buy the building with resources and score points.
* civilization card: buy the card with a number of resources depending on its position (1 to 4 resources).
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You can use tool to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If building cost is not specified you win points for each resources used depending on their values (3 for wood, 4 for brick, ...).
===Civilization card details===
Each card brings an immediate advantage (item on the top of the card) and some points during final scoring( item on the bottom of the card).
Place the mouse cursor on each card to see details.
===Feed your people===
Each agriculture level bring automatically 1 food.
You must use 1 food per people.
You can use any resource to feed your people if there is not enough food.
If you don't manage to feed your people: 10 points penalty.
===Game end===
The game end when:
* there is no more civilization card at the beginning of a round
* one building stack is empty at the end of a round
During the final scoring round, players win points using their civilization cards.
34d16399aa3a8e5f4902df2ff48e9e81de1c043f
Gamehelphaggis
0
22
48
2012-01-23T09:12:40Z
Sourisdudesert
1
Created page with " == Goal == Empty your hand before the other players. Additional points may be earned by capturing cards during play and betting that you will be first to shed all of your ca..."
wikitext
text/x-wiki
== Goal ==
Empty your hand before the other players.
Additional points may be earned by capturing cards during play and betting that you will be first to shed all of your cards.
== Rules summary ==
A valid card combination may be a set, a sequence or a bomb:
* a "set" is a group of any number of cards of the same rank (ex: one "8", two "5", ...).
* a "sequence" is a group of 3 or more cards of the same color with consecutive rank (ex: red 8, red 9, red 10)
* a "sequence" can also be a group of 2 or more pairs or larger sets of consecutive rank sharing the same suits between sets (ex: blue 3, green 3, blue 4, green 4, blue 5, green 5)
* a "bomb" is one of the following combination (ranked below from lowest to highest):
** 3-5-7-9 (in 4 different colors, "rainbow bomb")
** J-Q
** J-K
** Q-K
** J-Q-K
** 3-5-7-9 (in one color, "suited bomb")
Face cards can be used as wild cards to replace any cards in a "set" or a "sequence". Each player starts a round with a Jack, a Queen and a King. These face cards are public.
At your turn, you have to play a higher ranking combination with exactly the same type and same number of card that the first combination played. You can also pass. Bombs are an exception: you can play a bomb to beat any combination, except a higher bomb.
When all but one player pass in succession, the player who played the highest combination capture all cards played. Important exception: if the highest combination is a bomb, cards are captured by the player with the next higher combination. Then, a new trick starts. The winner of the last trick leads the new trick with any combination.
===Scoring overview===
* At the moment you shed your last card: 5 points per card in the hand of the player who held the most cards.
* Cards captured values: 2-4-6-8-10 = 0 point, 3-5-7-9 = 1 point, J = 2 points, Q = 3 points, K = 5 points.
* 30 points for a successful "Big bet", 15 points for a successful "Little bet". Points from unsuccessful bets are added to scores of the round's winner and to player(s) who did not bet.
da27e6a12b6310619db280f413a7b6b17f319f4f
Gamehelppuertorico
0
23
49
2012-01-23T09:14:58Z
Sourisdudesert
1
Created page with " == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the capta..."
wikitext
text/x-wiki
== Goal ==
Be the player with the most victory points at the end of the game by collecting:
* victory points earned for buildings
* victory point tokens earned at the captain phase
* conditional victory points earned at the end of the game for occupied large buildings
In case of a tie, the player owning the most doubloons and goods is the winner.
== Rules summary ==
The game is played over several rounds.
At the start of a round, the governor selects a role, then each player in turn selects a role.
At the end of the round, the governor token moves to the next player.
When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege.
Available roles are the following:
* Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations.
* Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations.
* Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet.
* Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available.
* Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available.
* Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship.
* Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none.
Please also note that occupied violet buildings have modifier effects for role actions.
End of game happens at the end of the round for which one of the following events comes to pass :
* there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase
* the last victory point token has been earned during the captain phase
* at least one of the players built on his 12th and last free space in the city.
== Playing online ==
Choosing a role : click on the role of your choice in the list on the right of your game board.
Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page).
Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege.
Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel.
Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated.
Builder role : click on the building that you want to buy. Placement on your board is automated.
Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame.
Prospector role : doubloon is earned immediately.
Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse.
== Available variant ==
Balanced game: implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page].
* The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons
* Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation.
Have a good game !
5a89fda7aa0b6e44383ce70410e470a81e1a8000
Gamehelpunclechestnuttablegype
0
24
50
2012-01-23T09:15:58Z
Sourisdudesert
1
Created page with " == Goal == Move all of your pieces to the Home Row opposite your starting position. == Rules summary == On their turn, each player can: 1) Roll one of his pieces and plac..."
wikitext
text/x-wiki
== Goal ==
Move all of your pieces to the Home Row opposite your starting position.
== Rules summary ==
On their turn, each player can:
1) Roll one of his pieces and place it back where it was
2) Move one of the pieces according to the rules for the face-up side
== Movement of the pieces: ==
* Flame: can move straight or diagonally in all directions
* Book: can move straight in all directions
* Swords: can move diagonnally in all directions
* Tree: can move straight forward or backwards, and diagonally forward
* Ear: cannot move at all !
* Hat: can move two steps straight then one step on the side, in all directions (like the knight in chess)
A piece can jump over an adjacent piece if there is an open space on the other side of the piece being jumped in the direction of the jumping piece's movement. The first time a piece is jumped over during a turn, it has to be rolled. After a jump, all pieces (except for the hat) can go on jumping as long as there is another valid jump available from the landing space.
A piece can freely move within its Home Row as long as it did not leave it. After it leaves though, it can't reenter its Home Row.
A piece arrived into his destination Home Row cannot move afterwards. Nonetheless, it can always finish a series of jumps before coming to a rest.
Playing online
Reordering your pieces: before starting to play, each player can reorder his pieces in his Home Row. To accomplish this, you can drag and drop a piece over another to exchange their positions. When you are done, click on the 'I'm finished' link above the play space. When all players are finished reordering, the game starts.
Select a piece: click on a piece. Available destinations for this piece (jumps comprised) are then highlighted.
Move a piece: click on the destination you want to move to. After a jump, if it is possible to make another jump, corresponding destinations will be highlighted. You can also stop where you are by clicking on the 'I'm finished' link above the play space.
Path selection: in order to move to a given destination, the hat can select between two moves. Either two steps forward then one on the side, or one step on the side then two steps forward. Distinct pieces may be rolled by following one path or another. Choosing the movement you want is done by clicking the link '1->2' or the link '2->1' (selected path is then highlighted), then by clicking the link 'I'm finished' above the play space.
Available variants
Random start: for a more random game, starting pieces are rolled (Ears are rolled again till getting only moving pieces).
Rule of Chaos: to encourage more chaos, a player cannot cross the middle of the board with any of their pieces until their starting Home Row has been emptied: all pieces have to be put in play at the same time.
Random start & Rule of Chaos : combination of the two previous variants.
Have a good game !
47a14dc24dc2483015390cae73fbdbd33cb69c3b
Gamehelpunclechestnuttablegype
0
24
51
50
2012-01-23T09:16:52Z
Sourisdudesert
1
wikitext
text/x-wiki
== Goal ==
Move all of your pieces to the Home Row opposite your starting position.
== Rules summary ==
On their turn, each player can:
* 1°) Roll one of his pieces and place it back where it was
* 2°) Move one of the pieces according to the rules for the face-up side
== Movement of the pieces: ==
* Flame: can move straight or diagonally in all directions
* Book: can move straight in all directions
* Swords: can move diagonnally in all directions
* Tree: can move straight forward or backwards, and diagonally forward
* Ear: cannot move at all !
* Hat: can move two steps straight then one step on the side, in all directions (like the knight in chess)
A piece can jump over an adjacent piece if there is an open space on the other side of the piece being jumped in the direction of the jumping piece's movement. The first time a piece is jumped over during a turn, it has to be rolled. After a jump, all pieces (except for the hat) can go on jumping as long as there is another valid jump available from the landing space.
A piece can freely move within its Home Row as long as it did not leave it. After it leaves though, it can't reenter its Home Row.
A piece arrived into his destination Home Row cannot move afterwards. Nonetheless, it can always finish a series of jumps before coming to a rest.
== Playing online ==
'''Reordering your pieces''': before starting to play, each player can reorder his pieces in his Home Row. To accomplish this, you can drag and drop a piece over another to exchange their positions. When you are done, click on the 'I'm finished' link above the play space. When all players are finished reordering, the game starts.
'''Select a piece''': click on a piece. Available destinations for this piece (jumps comprised) are then highlighted.
'''Move a piece''': click on the destination you want to move to. After a jump, if it is possible to make another jump, corresponding destinations will be highlighted. You can also stop where you are by clicking on the 'I'm finished' link above the play space.
'''Path selection''': in order to move to a given destination, the hat can select between two moves. Either two steps forward then one on the side, or one step on the side then two steps forward. Distinct pieces may be rolled by following one path or another. Choosing the movement you want is done by clicking the link '1->2' or the link '2->1' (selected path is then highlighted), then by clicking the link 'I'm finished' above the play space.
== Available variants ==
'''Random start''': for a more random game, starting pieces are rolled (Ears are rolled again till getting only moving pieces).
'''Rule of Chaos''': to encourage more chaos, a player cannot cross the middle of the board with any of their pieces until their starting Home Row has been emptied: all pieces have to be put in play at the same time.
'''Random start & Rule of Chaos''' : combination of the two previous variants.
Have a good game !
e0e1c7bf1bdc07eca3c7b1aa2d2d463ff891abe4
79
51
2012-03-11T14:43:52Z
Een
3
wikitext
text/x-wiki
== Goal ==
Move all of your pieces to the Home Row opposite your starting position.
== Rules summary ==
On their turn, each player can:
# Roll one of his pieces and place it back where it was
# Move one of the pieces according to the rules for the face-up side
== Movement of the pieces: ==
* Flame: can move straight or diagonally in all directions
* Book: can move straight in all directions
* Swords: can move diagonnally in all directions
* Tree: can move straight forward or backwards, and diagonally forward
* Ear: cannot move at all !
* Hat: can move two steps straight then one step on the side, in all directions (like the knight in chess)
A piece can jump over an adjacent piece if there is an open space on the other side of the piece being jumped in the direction of the jumping piece's movement. The first time a piece is jumped over during a turn, it has to be rolled. After a jump, all pieces (except for the hat) can go on jumping as long as there is another valid jump available from the landing space.
A piece can freely move within its Home Row as long as it did not leave it. After it leaves though, it can't reenter its Home Row.
A piece arrived into his destination Home Row cannot move afterwards. Nonetheless, it can always finish a series of jumps before coming to a rest.
== Playing online ==
'''Reordering your pieces''': before starting to play, each player can reorder his pieces in his Home Row. To accomplish this, you can drag and drop a piece over another to exchange their positions. When you are done, click on the 'I'm finished' link above the play space. When all players are finished reordering, the game starts.
'''Select a piece''': click on a piece. Available destinations for this piece (jumps comprised) are then highlighted.
'''Move a piece''': click on the destination you want to move to. After a jump, if it is possible to make another jump, corresponding destinations will be highlighted. You can also stop where you are by clicking on the 'I'm finished' link above the play space.
'''Path selection''': in order to move to a given destination, the hat can select between two moves. Either two steps forward then one on the side, or one step on the side then two steps forward. Distinct pieces may be rolled by following one path or another. Choosing the movement you want is done by clicking the link '1->2' or the link '2->1' (selected path is then highlighted), then by clicking the link 'I'm finished' above the play space.
== Available variants ==
'''Random start''': for a more random game, starting pieces are rolled (Ears are rolled again till getting only moving pieces).
'''Rule of Chaos''': to encourage more chaos, a player cannot cross the middle of the board with any of their pieces until their starting Home Row has been emptied: all pieces have to be put in play at the same time.
'''Random start & Rule of Chaos''' : combination of the two previous variants.
'''Have a good game !'''
cf24749138ddb9e1bb14c0a6a3ff344a8f7e2684
Gamehelpgosu
0
25
52
2012-01-23T09:19:41Z
Sourisdudesert
1
Created page with "Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr] == Victory == You win when you have 3 Victory Points or when you complete a s..."
wikitext
text/x-wiki
Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr]
== Victory ==
You win when you have 3 Victory Points or when you complete a special victory condition.
== Rules summary ==
During the Round, players play in turns, clockwise. The player with the Advantage Token starts to play.
When all players have passed, the Round ends and the Great Battle takes place.
===Great Battle===
Add up the military value of all your goblins. The owner of the most powerful army wins the Battle and scores a Victory Point. In case of a tie during the Battle, the player with the Advantage Token wins. All armies stay put and the players keep their hand of cards.
===One turn, one action===
* Play a goblin.
* Mutate a goblin.
* Spend 1 Activation Token to draw 1 card.
* Spend 2 Activation Tokens to draw 3 cards.
* Play an Activation Token on a goblin to activate its power (only 1 Token allowed per card).
* Pass (the player who pass has no turn until the next Round.).
===Goblins===
Every goblin in a Level are played from left to right in one row. Rows are ordered by ascending level from the bottom to the top.
You can't play more than 5 goblins per row.
'''Bakutos (level I)'''
* The first Bakuto is always free.
* Play a Bakuto is free if a Bakuto from the same clan is already in play.
* To play a Bakuto from a new clan, you have to discard 2 cards.
'''Heroes (level II)'''
* No more Heroes than Bakutos.
* In order to play a Hero, a Bakuto from the same clan must be in your army (no need to have him above the Bakuto).
'''Ōzekis (level III)'''
* No more Ōzekis than Heroes.
* In order to play an Ōzeki, a Hero and a Bakuto from the same clan must be in your army.
===Mutation===
You can mutate a goblin in another different goblin on the same
Level if you pay the Mutation Cost of the card:
Name the card to mutate.
Name et set aside the card that comes into play.
Discard the mutated card.
Apply any triggered effect.
Play the mutating card.
Apply any triggered effect.
Resolve Mutating effect.
A mutated carte is not « destroyed ».
Zombie Mutation: the mutating goblin may come from the
discard pile.
Goblins powers & details
A FREE card has no cards above nor on its right.
Carte emprisonnée : retournée, elle n'a ni pouvoir ni valeur militaire ni clan, mais conserve son nom et sa place dans l'armée.
Costs : the card costs (play, mutate, ...) are payed with cards discarded from your hand.
When the draw pile is empty and you have to draw, you shuffle the discard pile and make it the new draw pile.
The bonus mentionned into brackets (+...) apply if some opponent has more victory points.
The discard pile receive the discarded, destroyed or mutated cards. Any player can browse it anytime.
If a player wins his third Victory Point in a Round, he wins the game immediatly.
Board Game Arena would like to thanks mAxAttAck de gosulair.fr for this game help.
6b6358222feb2e53c7791d8d0c33a17076519651
53
52
2012-01-23T09:20:49Z
Sourisdudesert
1
wikitext
text/x-wiki
Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr]
== Victory ==
You win when you have 3 Victory Points or when you complete a special victory condition.
== Rules summary ==
During the Round, players play in turns, clockwise. The player with the Advantage Token starts to play.
When all players have passed, the Round ends and the Great Battle takes place.
===Great Battle===
Add up the military value of all your goblins. The owner of the most powerful army wins the Battle and scores a Victory Point. In case of a tie during the Battle, the player with the Advantage Token wins. All armies stay put and the players keep their hand of cards.
===One turn, one action===
* Play a goblin.
* Mutate a goblin.
* Spend 1 Activation Token to draw 1 card.
* Spend 2 Activation Tokens to draw 3 cards.
* Play an Activation Token on a goblin to activate its power (only 1 Token allowed per card).
* Pass (the player who pass has no turn until the next Round.).
===Goblins===
Every goblin in a Level are played from left to right in one row. Rows are ordered by ascending level from the bottom to the top.
You can't play more than 5 goblins per row.
'''Bakutos (level I)'''
* The first Bakuto is always free.
* Play a Bakuto is free if a Bakuto from the same clan is already in play.
* To play a Bakuto from a new clan, you have to discard 2 cards.
'''Heroes (level II)'''
* No more Heroes than Bakutos.
* In order to play a Hero, a Bakuto from the same clan must be in your army (no need to have him above the Bakuto).
'''Ōzekis (level III)'''
* No more Ōzekis than Heroes.
* In order to play an Ōzeki, a Hero and a Bakuto from the same clan must be in your army.
===Mutation===
You can mutate a goblin in another different goblin on the same
Level if you pay the Mutation Cost of the card:
* Name the card to mutate.
* Name et set aside the card that comes into play.
* Discard the mutated card.
* Apply any triggered effect.
* Play the mutating card.
* Apply any triggered effect.
* Resolve Mutating effect.
A mutated carte is not « destroyed ».
Zombie Mutation: the mutating goblin may come from the
discard pile.
===Goblins powers & details===
A FREE card has no cards above nor on its right.
Trapped card : no power, no value, no clan. It keeps its name and its place in the army.
Costs : the card costs (play, mutate, ...) are payed with cards discarded from your hand.
When the draw pile is empty and you have to draw, you shuffle the discard pile and make it the new draw pile.
The bonus mentionned into brackets (+...) apply if some opponent has more victory points.
The discard pile receive the discarded, destroyed or mutated cards. Any player can browse it anytime.
If a player wins his third Victory Point in a Round, he wins the game immediatly.
Board Game Arena would like to thanks mAxAttAck de gosulair.fr for this game help.
2de59874bb4c8b039c82523b624075e1a4da29c1
66
53
2012-02-06T01:12:27Z
Jleidich
100
/* Mutation */
wikitext
text/x-wiki
Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr]
== Victory ==
You win when you have 3 Victory Points or when you complete a special victory condition.
== Rules summary ==
During the Round, players play in turns, clockwise. The player with the Advantage Token starts to play.
When all players have passed, the Round ends and the Great Battle takes place.
===Great Battle===
Add up the military value of all your goblins. The owner of the most powerful army wins the Battle and scores a Victory Point. In case of a tie during the Battle, the player with the Advantage Token wins. All armies stay put and the players keep their hand of cards.
===One turn, one action===
* Play a goblin.
* Mutate a goblin.
* Spend 1 Activation Token to draw 1 card.
* Spend 2 Activation Tokens to draw 3 cards.
* Play an Activation Token on a goblin to activate its power (only 1 Token allowed per card).
* Pass (the player who pass has no turn until the next Round.).
===Goblins===
Every goblin in a Level are played from left to right in one row. Rows are ordered by ascending level from the bottom to the top.
You can't play more than 5 goblins per row.
'''Bakutos (level I)'''
* The first Bakuto is always free.
* Play a Bakuto is free if a Bakuto from the same clan is already in play.
* To play a Bakuto from a new clan, you have to discard 2 cards.
'''Heroes (level II)'''
* No more Heroes than Bakutos.
* In order to play a Hero, a Bakuto from the same clan must be in your army (no need to have him above the Bakuto).
'''Ōzekis (level III)'''
* No more Ōzekis than Heroes.
* In order to play an Ōzeki, a Hero and a Bakuto from the same clan must be in your army.
===Mutation===
You can mutate a goblin in another different goblin on the same
Level if you pay the Mutation Cost of the card:
* Name the card to mutate.
* Name and set aside the card that comes into play.
* Discard the mutated card.
* Apply any triggered effect.
* Play the mutating card.
* Apply any triggered effect.
* Resolve Mutating effect.
A mutated card is not « destroyed ».
Zombie Mutation: the mutating goblin may come from the
discard pile.
===Goblins powers & details===
A FREE card has no cards above nor on its right.
Trapped card : no power, no value, no clan. It keeps its name and its place in the army.
Costs : the card costs (play, mutate, ...) are payed with cards discarded from your hand.
When the draw pile is empty and you have to draw, you shuffle the discard pile and make it the new draw pile.
The bonus mentionned into brackets (+...) apply if some opponent has more victory points.
The discard pile receive the discarded, destroyed or mutated cards. Any player can browse it anytime.
If a player wins his third Victory Point in a Round, he wins the game immediatly.
Board Game Arena would like to thanks mAxAttAck de gosulair.fr for this game help.
a62e06b222c75ef7b96e85f1dc657b36d24fcd85
67
66
2012-02-06T01:14:28Z
Jleidich
100
/* Goblins powers & details */
wikitext
text/x-wiki
Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr]
== Victory ==
You win when you have 3 Victory Points or when you complete a special victory condition.
== Rules summary ==
During the Round, players play in turns, clockwise. The player with the Advantage Token starts to play.
When all players have passed, the Round ends and the Great Battle takes place.
===Great Battle===
Add up the military value of all your goblins. The owner of the most powerful army wins the Battle and scores a Victory Point. In case of a tie during the Battle, the player with the Advantage Token wins. All armies stay put and the players keep their hand of cards.
===One turn, one action===
* Play a goblin.
* Mutate a goblin.
* Spend 1 Activation Token to draw 1 card.
* Spend 2 Activation Tokens to draw 3 cards.
* Play an Activation Token on a goblin to activate its power (only 1 Token allowed per card).
* Pass (the player who pass has no turn until the next Round.).
===Goblins===
Every goblin in a Level are played from left to right in one row. Rows are ordered by ascending level from the bottom to the top.
You can't play more than 5 goblins per row.
'''Bakutos (level I)'''
* The first Bakuto is always free.
* Play a Bakuto is free if a Bakuto from the same clan is already in play.
* To play a Bakuto from a new clan, you have to discard 2 cards.
'''Heroes (level II)'''
* No more Heroes than Bakutos.
* In order to play a Hero, a Bakuto from the same clan must be in your army (no need to have him above the Bakuto).
'''Ōzekis (level III)'''
* No more Ōzekis than Heroes.
* In order to play an Ōzeki, a Hero and a Bakuto from the same clan must be in your army.
===Mutation===
You can mutate a goblin in another different goblin on the same
Level if you pay the Mutation Cost of the card:
* Name the card to mutate.
* Name and set aside the card that comes into play.
* Discard the mutated card.
* Apply any triggered effect.
* Play the mutating card.
* Apply any triggered effect.
* Resolve Mutating effect.
A mutated card is not « destroyed ».
Zombie Mutation: the mutating goblin may come from the
discard pile.
===Goblins powers & details===
A FREE card has no cards above it nor to its right.
Trapped card : no power, no value, no clan. It keeps its name and place in the army.
Costs : the card costs (play, mutate, ...) are payed with cards discarded from your hand.
When the draw pile is empty and you have to draw, you shuffle the discard pile and make it the new draw pile.
The bonus mentioned in brackets (+...) apply if some opponent has more victory points.
The discard pile receives the discarded, destroyed or mutated cards. Any player can browse it anytime.
If a player wins his third Victory Point in a Round, he wins the game immediatly.
Board Game Arena would like to thanks mAxAttAck de gosulair.fr for this game help.
aeee202f11e1fef25f50b04ff56e9895ee5263d2
Gamehelptroyes
0
26
54
2012-01-23T09:25:01Z
Sourisdudesert
1
Created page with " == Goal == Be the player with the most victory points at the end of the game. == Rules summary == (This rules summary is based on the game help written by [http://boardgam..."
wikitext
text/x-wiki
== Goal ==
Be the player with the most victory points at the end of the game.
== Rules summary ==
(This rules summary is based on the game help written by [http://boardgamegeek.com/user/pregremlin Andrew Agard] for Board Game Geek, under Creative Commons license. Please see [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] here for details. Thank you Andrew !)
===Initial Placement===
* In clockwise order place a citizen in empty space of one building
* Continue in counter clockwise order from last player and so on until all citizens placed
===Game play===
====Phase 0: Reveal the Activity cards====
Reveal activity card for each color corresponding to current round (first 3 rounds only)
====Phase 1: Income and salaries====
Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP
====Phase 2: Assembling the workforce====
Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district
====Phase 3: Events====
Reveal top red and white or yellow Event and place to right of queue (unlimited Events)
Events take effect from left to right
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Actions====
See below.
====Phase 5: End of the round====
Receive deniers from district
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Pass start player card left.
===Actions===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Activate Activity Card====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Combat Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Place a citizen on building====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Use Agriculture====
* Gain number of deniers equal to total value divided by 2 (round down)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
fbdfaed8129e77bd038dee3623968940c24674a0
Gamehelptobago
0
27
55
2012-01-23T09:26:14Z
Sourisdudesert
1
Created page with " == Goal == Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players. == Rules summary == On their turn, each player..."
wikitext
text/x-wiki
== Goal ==
Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not is sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map indicate show where the treasure can be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or one space only when your ATV goes from one land type to another.
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
The game ends after sharing the treasure for which the deck of treasure cards has been exhausted.
Have a good game !
1cf926fcbeaf776e08a8d7a0e3228b35b9f0c542
81
55
2012-03-11T14:48:48Z
Een
3
wikitext
text/x-wiki
== Goal ==
Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not is sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map indicate show where the treasure can be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or one space only when your ATV goes from one land type to another.
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
The game ends after sharing the treasure for which the deck of treasure cards has been exhausted.
'''Have a good game !'''
b3a0671ef523f43497b67a815ac6f839a04dbd1b
87
81
2012-03-31T00:48:04Z
Avron
453
/* 1) Play a clue card from his hand */
wikitext
text/x-wiki
== Goal ==
Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map indicate where the treasure can be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or one space only when your ATV goes from one land type to another.
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
The game ends after sharing the treasure for which the deck of treasure cards has been exhausted.
'''Have a good game !'''
1ce82af1085c3662b22e442d6634e1ed2c342517
Gamehelpamyitis
0
28
56
2012-01-23T09:29:49Z
Sourisdudesert
1
Created page with " == Victory == The player with the most victory points (VP) wins the game. == Rules summary == Thank you [http://boardgamegeek.com/user/sdetoni Steven] for this game help ..."
wikitext
text/x-wiki
== Victory ==
The player with the most victory points (VP) wins the game.
== Rules summary ==
Thank you [http://boardgamegeek.com/user/sdetoni Steven] for this game help (original file is [http://boardgamegeek.com/filepage/64197/synopses-of-amyitis-rules there]).
Game starts, and recycles the 3 phases, setup, action, maintenance, until:
* 4 or less garden tiles are left after a maintenance phase for 3/4 players.
* 3 or less garden tiles are left after a maintenance phase for 2 players.
===Setup Phase===
Shuffle all Craftsmen cards and Layout as below.
* 2 players: 2 groups of three cards.
* 3 players: 3 groups of three cards.
* 4 players: 4 groups of three cards.
Players with Bankers earn Income (1 coin, 2 coins, or 2 coins & 2 VPs).
===Action Phase===
'''Passing'''
Place cube on Pass space; each time that player Passes afterward, he
earns 1 coin.
'''Purchasing Workers'''
Recruit a Craftsman from a set; the first in a set (3 horizontal cards) costs no coins, the second cost 1 coin, and the third costs 2 coins. Turn over card to display coin upon chosen card, which signifies the cost of the next card.
Merchant: Take 1 camel into the players supply.
Engineer: Place 1 cube of a player on an irrigation marker and get 2 VPs. The cube placement must trace an unbroken path of irrigation cubes to the river.
Priest: Place 1 cube of a player into one Temple’s line of petitioners (each Temple will earn something in the Maintenance Phase). Place cube from left and shift all other cubes to the right. Cubes that drop off from the right are placed back into supply.
Farmer: Place 1 cube of a player on the left most open field space and take that Resource into Supply. If that Resource is Wine, the field is cleared and whoever had a majority of cubes in that field gets a Gardener card if one is available. If tied, the cube colour furthest to the right wins the gardener card.
'''Trading/Caravanning'''
Move the Caravan by paying at least 1 Camel token and moving as many spaces as Camels paid plus up to as many spaces as allowed by the current Caravan card.
A Caravan cannot be moved to a place where a player cannot fulfil the demands of that city.
If the Caravan moves into Babylon either 1 Resource token must be given up for 3 VPs or 2 resource tokens can be given for 6 VPs; that player also places one irrigation cube.
In some cities a player can hire Bankers and Caravaneers, as well as expand their Palace (bonus one-time VPs are added when cards are purchased). Pay the required resource to acquire these upgrade cards.
In four of the cities there are Plants available. Some Plants are better than others and cost more (i.e. 2 resource tokens instead of 1).
There are four levels to the Hanging Gardens, with level 1 Plants being able to be planted on its first level.
Level 2 Plants may also be planted in level 1 Hanging Gardens.
Gardeners can improve a Plant’s quality, allowing level 1 Plants to be planted on the Wonder’s second level or even its third; or allowing a level 2 Plant to be planted on the third level. That is, 1 or more gardener cards can be used on a plant to increases its quality.
The Hanging Gardens’ fourth level requires a level 3 plant only.
As soon as Plants are paid for, they are planted.
The player who bought the Plant gains the prizes on the Wonder’s tile.
A player who controls the irrigation around that tile (i.e. the most number of their colour cubes) scores VPs equal to the Plant’s initial level (not including spent gardener cards). If there is tie, then no VPs are given.
Neutral grey cubes are added to empty irrigation spots of adjacent planted tile areas.
Once bonuses and VPs have been award, the plant card is turned over in the caravan board to show a different plant on offer for that city/area.
===Maintenance Phase===
Temple Procession is controlled by the last player in the round; they place 1 cube of that players colour into one of the Temples of their choice, and 1 neutral cube into each of the other temples (i.e. 2 grey cubes total).
Temples provide benefits to 1 player in a 2 player game, or 2 players in a 3-4 player game; ties for majority are broken by whose cube is closest to the right/exit.
Award bonuses for each temple:
Ishtar 1st Gets choice of a camel token or a coin.
2nd Gets what the 1st place didn’t want.
Marduk 1st Gets 2 VPs.
2nd Gets 1 VPs.
Tammouz 1st Gets to add a clue to the resource field of their choice.
2nd Gets to swap one of their resource tokens from supply, but not for wine.
Players check goods in their Supply for resource spoilage and adjust the token number they can keep between major game rounds.
Level 0,1 Caravaneers can keep up to 2 resource tokens.
Level 2 Caravaneers can keep up to 4 resource tokens.
The Starting Player card is passed clockwise. Re-shuffle craftsmen cards; go to setup phase to complete another game round.
===End Game===
Game ends when the follow conditions are met for the number people playing.
2 Players: When 3 garden tiles are left or less at the end of major game round.
5 or 6 Wonder tiles gained add additional 5 VPs,
7 Wonder tiles gained, add 10 VPs.
3 Players: When 4 garden tiles are left or less at the end of major game round.
4 or 5 Wonder tiles gained add additional 5 VPs,
6 Wonder tiles gained, add 10 VPs.
4 Players: When 4 garden tiles are left or less at the end of major game round.
3 or 4 Wonder tiles gained add additional 5 VPs,
5 Wonder tiles gained, add 10 VPs.
Each player scores 1 additional VP for each resource token remaining in his stock (nothing for the camels and the coins).
Total points = Current VPs
+ Resources Token Left
+ Bonus for number of garden tiles planted.
7f310513787f643d738ab499101925bd3ba58b17
Translation guidelines
0
18
57
43
2012-01-23T18:24:35Z
Een
3
/* I fixed some translations, but they don't appear to have changed on the site ? */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated ? ==
Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later...
== Who should translate ? ==
This is important : only native speakers of a given language should translate in this language.
When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronomical rules usual for the gaming audience of their country.
As Board Game Arena's team's mothertongue is french, we will take charge of the french translations.
We will also release the first version of the english translation. As we are not perfect speakers of Shakespeare's language, these translation will be open for review and correction from native english speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into ? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language.
== I fixed some translations, but they don't appear to have changed on the site ? ==
Translation files are updated by a nightly batch, so you just have to wait till the morrow for your changes to appear on the site.
== How long will it be possible to change the translations ? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating ? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
f7af8e4384b62aa3f98aed12555045fe22559d9a
63
57
2012-01-28T05:00:40Z
Azraeldeadlight
63
/* Who should translate ? */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated ? ==
Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later...
== Who should translate ? ==
This is important: only native speakers of a given language should translate in this language.
When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country.
As Board Game Arena's team's mother tongue is French, we will take charge of the French translations.
We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into ? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language.
== I fixed some translations, but they don't appear to have changed on the site ? ==
Translation files are updated by a nightly batch, so you just have to wait till the morrow for your changes to appear on the site.
== How long will it be possible to change the translations ? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating ? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
03a81a5f108268605fffaeaf1179a98eeeed1e12
68
63
2012-02-07T07:32:09Z
Laszlosaurus
116
Great idea to wikify everything!
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated? ==
Every string of text for the main site interface and for the games' interfaces are 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometime later...
== Who should translate? ==
This is important: only translate text into a given language if you are a native speaker of the language.
When translating a game, the translator should know the game thoroughly and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country.
As Board Game Arena's team's mother tongue is French, we will take charge of the French translations.
We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the morrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
5342971093e24707f58f475c7b88ca60b9f6c8e5
Gamehelpstoneage
0
21
58
47
2012-01-26T03:44:39Z
Oedin
35
/* Game end */
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, with your civilization cards.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players placed their people on "rings" (1 people per ring).
Special rules with 2 players:
* only 1 player in each of the following: forest, clay pit, quarry, and river.
* only 2 of the 3 places: tool maker, hut, and field may be filled in each round.
Special rules with 3 players:
* maximum of 2 players in each of the following: forest, clay pit, quarry, and river.
* only 2 of the 3 places: tool maker, hut, and field may be filled in each round.
===Use the actions of your placed people===
Each player uses all his placed people in any order, and realize the corresponding actions:
* hunting grounds, forest, clay pit, quarry, and river: roll 1 dice per people and take corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* field: increase agriculture level.
* tool: get one tool.
* hut: get one additional people.
* building: buy the building with resources and score points.
* civilization card: buy the card with a number of resources depending on its position (1 to 4 resources).
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You can use tool to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If building cost is not specified you win points for each resources used depending on their values (3 for wood, 4 for brick, ...).
===Civilization card details===
Each card brings an immediate advantage (item on the top of the card) and some points during final scoring( item on the bottom of the card).
Place the mouse cursor on each card to see details.
===Feed your people===
Each agriculture level bring automatically 1 food.
You must use 1 food per people.
You can use any resource to feed your people if there is not enough food.
If you don't manage to feed your people: 10 points penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
During the final scoring round, players win points using their civilization cards.
f95d7d0ce2d15cea166eddeeb542ba0fc8c1d59c
59
58
2012-01-26T03:46:04Z
Oedin
35
/* Feed your people */
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, with your civilization cards.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players placed their people on "rings" (1 people per ring).
Special rules with 2 players:
* only 1 player in each of the following: forest, clay pit, quarry, and river.
* only 2 of the 3 places: tool maker, hut, and field may be filled in each round.
Special rules with 3 players:
* maximum of 2 players in each of the following: forest, clay pit, quarry, and river.
* only 2 of the 3 places: tool maker, hut, and field may be filled in each round.
===Use the actions of your placed people===
Each player uses all his placed people in any order, and realize the corresponding actions:
* hunting grounds, forest, clay pit, quarry, and river: roll 1 dice per people and take corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* field: increase agriculture level.
* tool: get one tool.
* hut: get one additional people.
* building: buy the building with resources and score points.
* civilization card: buy the card with a number of resources depending on its position (1 to 4 resources).
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You can use tool to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If building cost is not specified you win points for each resources used depending on their values (3 for wood, 4 for brick, ...).
===Civilization card details===
Each card brings an immediate advantage (item on the top of the card) and some points during final scoring( item on the bottom of the card).
Place the mouse cursor on each card to see details.
===Feed your people===
Each agriculture level automatically give you 1 food.
You must use 1 food per person.
You can use any resource to feed your people if there is not enough food.
If you don't manage to feed your people, you lose 10 points as a penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
During the final scoring round, players win points using their civilization cards.
aa2efd8d0fcce02506a62d8dae4e1b0669bb8239
60
59
2012-01-26T03:47:06Z
Oedin
35
/* Buildings */
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, with your civilization cards.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players placed their people on "rings" (1 people per ring).
Special rules with 2 players:
* only 1 player in each of the following: forest, clay pit, quarry, and river.
* only 2 of the 3 places: tool maker, hut, and field may be filled in each round.
Special rules with 3 players:
* maximum of 2 players in each of the following: forest, clay pit, quarry, and river.
* only 2 of the 3 places: tool maker, hut, and field may be filled in each round.
===Use the actions of your placed people===
Each player uses all his placed people in any order, and realize the corresponding actions:
* hunting grounds, forest, clay pit, quarry, and river: roll 1 dice per people and take corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* field: increase agriculture level.
* tool: get one tool.
* hut: get one additional people.
* building: buy the building with resources and score points.
* civilization card: buy the card with a number of resources depending on its position (1 to 4 resources).
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You can use tool to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If the building cost is not specified, you win points for each of the resources used, depending on their values (3 for wood, 4 for brick, ...).
===Civilization card details===
Each card brings an immediate advantage (item on the top of the card) and some points during final scoring( item on the bottom of the card).
Place the mouse cursor on each card to see details.
===Feed your people===
Each agriculture level automatically give you 1 food.
You must use 1 food per person.
You can use any resource to feed your people if there is not enough food.
If you don't manage to feed your people, you lose 10 points as a penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
During the final scoring round, players win points using their civilization cards.
6e501537cfc05012c6080c793b3e5560152b5039
97
60
2012-05-18T23:55:17Z
Spacediver
718
slight rewrite, according to first learning experience
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, according to civilization cards acquired by you.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings).
Special rules for game with 2 players only:
* no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
Special rules for game with 3 players only:
* no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
===Use the actions of your placed people===
Each player uses all his placed people in any order, and perform the corresponding actions:
* '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* '''field''': increase agriculture level.
* ''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded).
* '''hut''': get one additional people.
* '''building card''': buy the building with resources, scoring some points.
* '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied.
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You may use tools to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...).
===Civilization card details===
Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card).
Place the mouse cursor on each card to see details in the tooltip.
Note that at the list of your acuired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore.
===Feed your people===
Each agriculture level automatically give you 1 food.
You must provide 1 food per person.
You may use any resource to feed your people if there is not enough food.
If you don't manage to feed your people by means above, you lose 10 points as a penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
Final number of points for each player is summed out of
* points earned during the game by acquiring buildings, minus food penalties,
* multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc).
97b0aa912d4b9b69c2f7376b22be6e9e7072bcb4
98
97
2012-05-18T23:56:20Z
Spacediver
718
/* Use the actions of your placed people */
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, according to civilization cards acquired by you.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings).
Special rules for game with 2 players only:
* no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
Special rules for game with 3 players only:
* no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
===Use the actions of your placed people===
Each player uses all his placed people in any order, and perform the corresponding actions:
* '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* '''field''': increase agriculture level.
* '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded).
* '''hut''': get one additional people.
* '''building card''': buy the building with resources, scoring some points.
* '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied.
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You may use tools to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...).
===Civilization card details===
Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card).
Place the mouse cursor on each card to see details in the tooltip.
Note that at the list of your acuired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore.
===Feed your people===
Each agriculture level automatically give you 1 food.
You must provide 1 food per person.
You may use any resource to feed your people if there is not enough food.
If you don't manage to feed your people by means above, you lose 10 points as a penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
Final number of points for each player is summed out of
* points earned during the game by acquiring buildings, minus food penalties,
* multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc).
287ea7fa1fd741d4cd21c7b7acc067293f636bc6
99
98
2012-05-18T23:57:16Z
Spacediver
718
/* Civilization card details */
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, according to civilization cards acquired by you.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings).
Special rules for game with 2 players only:
* no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
Special rules for game with 3 players only:
* no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
===Use the actions of your placed people===
Each player uses all his placed people in any order, and perform the corresponding actions:
* '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* '''field''': increase agriculture level.
* '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded).
* '''hut''': get one additional people.
* '''building card''': buy the building with resources, scoring some points.
* '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied.
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You may use tools to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...).
===Civilization card details===
Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card).
Place the mouse cursor on each card to see details in the tooltip.
Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore.
===Feed your people===
Each agriculture level automatically give you 1 food.
You must provide 1 food per person.
You may use any resource to feed your people if there is not enough food.
If you don't manage to feed your people by means above, you lose 10 points as a penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
Final number of points for each player is summed out of
* points earned during the game by acquiring buildings, minus food penalties,
* multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc).
8055236dec4e47f0d97b4a11798e1d8683139159
Contact us
0
9
61
21
2012-01-28T04:56:06Z
Azraeldeadlight
63
/* E-mail contact */
wikitext
text/x-wiki
'''Board Game Arena''' is located in France.
== E-mail contact ==
contact(at)boardgamearena.com
We receive *a lot* of e-mails. Please do not send us an e-mail if:
* ... you want to report a bug, please do it in the corresponding forum.
* ... you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile
== Responsible ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
b19d027459acac0ecff2c30a0bf71a353da4d5e0
Help
0
4
62
13
2012-01-28T04:56:47Z
Azraeldeadlight
63
/* Detailed help */
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena]]
** [[About us]]
** [[Club Board Game Arena]]
** [[Contact us]]
=== Detailed help ===
* [[Getting started]]
* [[Referral]]
* [[Browser support]]
* [[Moderation and grades]]
* [[Game clock]]
* [[Rating]]
* [[Reputation]]
* [[Translation guidelines]]
c6067b5fc3f21568031e1b54885fd097134d4f1d
77
62
2012-03-01T16:30:05Z
Yserbius123
229
Added list of games
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena]]
** [[About us]]
** [[Club Board Game Arena]]
** [[Contact us]]
=== Detailed help ===
* [[Getting started]]
* [[Referral]]
* [[Browser support]]
* [[Moderation and grades]]
* [[Game clock]]
* [[Rating]]
* [[Reputation]]
* [[Translation guidelines]]
== Games ==
* [[Gamehelphaggis|Haggis]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelpdominion|Dominion]]
* [[Gamehelpyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpunclechesnutstablegype|Uncle Chesnut's Table Gype]]
7d07756ae02893aca53910e7f887b90075704c79
Faq
0
3
64
24
2012-02-02T00:26:04Z
Sunrise
21
/* What is forbidden on Board Game Arena? */
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
30db44a0c18a4716b60b3f10ceeebfaab2fd2f29
74
64
2012-02-21T23:26:39Z
Sunrise
21
/* Meeting players and starting games */
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
When you win a 2 players game: 1 point.
When you win a 3 players game: 1.5 points.
When you win a 4 players game: 2 points.
etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
abd36ffcfe6194a01564f66ee1d74aadb48ddd82
75
74
2012-02-21T23:27:11Z
Sunrise
21
/* Meeting players and starting games */
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
edeaf919c942259f6571aeb8fcdae43a6f0ce9e4
100
75
2012-05-19T00:05:58Z
Spacediver
718
/* I joined a game. When does the game start? */ (removed confusion of 'around the table' with 'joined the table')
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamlist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
a22edcd73f518e3d5b1421a84dfce0e7bd9832b4
Gamehelpdominion
0
29
65
2012-02-02T00:54:39Z
Sunrise
21
Created page with "'''Goal''' Be the player with the most victory points at the end of the game. '''Ending Condition''' The ''Province'' stack being depleted, or 3 stacks of cards being deplete..."
wikitext
text/x-wiki
'''Goal'''
Be the player with the most victory points at the end of the game.
'''Ending Condition'''
The ''Province'' stack being depleted, or 3 stacks of cards being depleted.
'''Setup'''
Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand.
'''Overview'''
The A-B-C rule makes it easy to remember the play order. On a player's turn:
A: Action
The player may play an action card.
Each player is allowed 1 action per turn by default. Certain action cards provide additional actions.
B: Buy
After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile.
Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys.
C: Cleanup
After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck.
The game progresses in clockwise order until ending conditions are met.
'''Tie-breaker'''
If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If these is still a tie, all tied players rejoice in a shared victory.
805fe71c99ac402dc86dcc9baf048905fac8d1a2
71
65
2012-02-18T20:50:29Z
Camaroman
213
wikitext
text/x-wiki
'''Goal'''
Be the player with the most victory points at the end of the game.
'''Ending Condition'''
The ''Province'' stack being depleted, or 3 stacks of cards being depleted.
'''Setup'''
Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand.
'''Overview'''
The A-B-C rule makes it easy to remember the play order. On a player's turn:
A: Action
The player may play an action card.
Each player is allowed 1 action per turn by default. Certain action cards provide additional actions.
B: Buy
After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile.
Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys.
C: Cleanup
After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck.
The game progresses in clockwise order until ending conditions are met.
'''Tie-breaker'''
If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If there is still a tie, all tied players rejoice in a shared victory.
bc9f64e7b84f58a37339e487710ed67e3593ba84
76
71
2012-02-26T01:36:51Z
Dclaw25
248
wikitext
text/x-wiki
'''Goal'''
Be the player with the most victory points at the end of the game.
'''Ending Condition'''
The ''Province'' stack being depleted, or 3 stacks of cards being depleted.
'''Setup'''
Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand.
'''Overview'''
The A-B-C rule makes it easy to remember the play order. On a player's turn:
A: Action:
The player may play an action card.
Each player is allowed 1 action per turn by default. Certain action cards provide additional actions.
B: Buy:
After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile.
Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys.
C: Cleanup:
After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck.
The game progresses in clockwise order until ending conditions are met.
'''Tie-breaker'''
If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If there is still a tie, all tied players rejoice in a shared victory.
98e728c742c8883c076384792bd60f9fb34bc840
Browser support
0
13
69
36
2012-02-07T08:43:53Z
Laszlosaurus
116
emphasized recommended browsers and provided download links
wikitext
text/x-wiki
[[Category:Help]]
<h3>For the best experience, we recommend:</h3>
* '''Google Chrome 10+''' [http://www.google.com/chrome Windows] [http://www.google.com/chrome?platform=mac Mac] [http://www.google.com/chrome?platform=linux Linux]
* '''Mozilla Firefox 4+''' [http://www.mozilla.org/products/firefox/ Windows] [http://www.mozilla.org/products/firefox/ Mac] [http://www.mozilla.org/products/firefox/ Linux]
Board Game Arena takes advantage of the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download or update, no plugins to install, etc.
Consequently, to play you need to use a modern web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be.
This website makes intensive use of Javascript and your browser's graphics capabilities. Thus, if you want to have the best gaming experience with Board Game Arena, you should use one of the browsers listed above. However, we officially support the following browsers:
* Google Chrome 4+
* Mozilla Firefox 3.5+
* Internet Explorer 9
* Internet Explorer 8 (partial support for IE7)
* Safari 4+
(Note: We do NOT support play on iPads or similar tablets.)
3872e0f01d029cea980494755aa10bf990d93e78
Grade
0
30
70
2012-02-09T01:48:50Z
Cthulpiss
110
Created page with "Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit o..."
wikitext
text/x-wiki
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== All grades ==
* '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel).
* '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points.
* '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade.
* '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased.
* '''Archangel''': this is the Board Game Arena administrators' grade.
* '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...)
* '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time.
71f29ae0ffe6a00b8e4a457aacd391fde8cee61d
Rating
0
16
72
38
2012-02-20T05:32:55Z
Amagila
220
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How is my ELO ranking computed ? ==
The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
Let's try to make it simple: the points you win/lose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you lose at the same table, your ranking will decrease a little. And so on ...
In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
== Okay, but I want to know the formula ! ==
At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* Table Level (TL) is the average of ELO ratings of all players at this table.
* The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player).
* The performance (P) of a player is TL+S.
* The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
c3ec166f7f82b32d6e93d7108888b93f71461a40
Reputation
0
17
73
40
2012-02-20T05:34:23Z
Amagila
220
wikitext
text/x-wiki
[[Category:Help]]
== What is reputation ? ==
On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance.
To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items:
* Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png)
* % of games you finished
* % of games you finished with no clock penalties
Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits.
== How to increase my reputation / what makes my reputation decrease ? ==
At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks.
* a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player.
* a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player.
You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change.
As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player.
By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information.
== Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png ==
* Be polite ! Say at least "hello" and "good luck" at the beginning of the game. "good game" ("gg") at the end of the game.
* When you need some time to think, click on "I would like to think a little" link.
* Stay calm in any circumstances: it's a game.
* Don't press your opponent to play if he has some time left.
* If you really can't finish the game (this is not supposed to happened...), then say you are sorry and leave the game by your own to save your opponents time.
* Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!).
* Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation.
== What are the consequences of a bad reputation ? ==
A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you.
It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents.
82e240a99d58813f6fa5c065f5d6a831f89af9d4
Gamehelpdragonheart
0
31
78
2012-03-02T15:38:38Z
Yserbius123
229
New page
wikitext
text/x-wiki
==Summary==
Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down.
==Goal==
To have the most points by the end of the game.
==Game Start==
At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board.
==End==
The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 2 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game.
==Turns==
Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship.
==Cards==
There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it it. Arrows on the board indicate what cards can take what.
* ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf.
* ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board.
* ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards.
* ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress.
* ''Troll'': Placing this card allows the player to take the sorceress pile.
* ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board.
* ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent.
* ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon.
* ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards were played ends the game.
* ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus two extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand.
daaa8873bc1834aa5742568b1a229c985f2a521d
95
78
2012-04-23T19:30:36Z
Sourisdudesert
1
wikitext
text/x-wiki
==Summary==
Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down.
==Goal==
To have the most points by the end of the game.
==Game Start==
At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board.
==End==
The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 2 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game.
==Turns==
Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship.
==Cards==
There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it it. Arrows on the board indicate what cards can take what.
* ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf.
* ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board.
* ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards.
* ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress.
* ''Troll'': Placing this card allows the player to take the sorceress pile.
* ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board.
* ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent.
* ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon.
* ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards were played ends the game.
* ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand.
a6a9718046f5d9072f2785309784178d640abc81
96
95
2012-04-30T20:53:02Z
Christopheryoder
621
/* Cards */
wikitext
text/x-wiki
==Summary==
Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down.
==Goal==
To have the most points by the end of the game.
==Game Start==
At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board.
==End==
The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 2 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game.
==Turns==
Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship.
==Cards==
There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what.
* ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf.
* ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board.
* ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards.
* ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress.
* ''Troll'': Placing this card allows the player to take the sorceress pile.
* ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board.
* ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent.
* ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon.
* ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards were played ends the game.
* ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand.
a9e72a95fb991b06d79eaf44b61835a529800b60
Gamehelppuertorico
0
23
80
49
2012-03-11T14:46:48Z
Een
3
wikitext
text/x-wiki
== Goal ==
Be the player with the most victory points at the end of the game by collecting:
* victory points earned for buildings
* victory point tokens earned at the captain phase
* conditional victory points earned at the end of the game for occupied large buildings
In case of a tie, the player owning the most doubloons and goods is the winner.
== Rules summary ==
The game is played over several rounds.
At the start of a round, the governor selects a role, then each player in turn selects a role.
At the end of the round, the governor token moves to the next player.
When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege.
Available roles are the following:
* Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations.
* Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations.
* Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet.
* Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available.
* Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available.
* Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship.
* Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none.
Please also note that occupied violet buildings have modifier effects for role actions.
End of game happens at the end of the round for which one of the following events comes to pass :
* there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase
* the last victory point token has been earned during the captain phase
* at least one of the players built on his 12th and last free space in the city.
== Playing online ==
Choosing a role : click on the role of your choice in the list on the right of your game board.
* Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page).
* Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege.
* Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel.
* Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated.
* Builder role : click on the building that you want to buy. Placement on your board is automated.
* Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame.
* Prospector role : doubloon is earned immediately.
Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse.
== 'Balanced game' variant ==
This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page].
* The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons
* Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation.
'''Have a good game !'''
0b804619fb7d51434ad55e5ff5672a4cd2fdbba9
Gamehelpsaboteur
0
32
82
2012-03-11T18:05:12Z
Een
3
Created page with " == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with othe..."
wikitext
text/x-wiki
== Goal ==
Get as many gold nuggets as possible during the three rounds of the game.
In order to do so,
# if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards
# if you are a '''saboteur''', you must, in association with other gold diggers, prevent the gold diggers to get to the treasure.
Your role (gold digger or saboteur) will be randomly selected at the start of each round.
== Rules summary ==
On your turn, you must click on a card from your hand to select it, then play this card or discard it.
You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card.
The cards are of several types:
* 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card.
* 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score).
* 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you.
* 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about.
* 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove.
== Cards in play ==
* 44 'Path' cards
* 9 'Sabotage' cards (three for each tool)
* 6 'Repair a tool' cards (two for each tool)
* 3 'Repair a tool among these two' cards (one for each combination of two tools)
* 5 'Map' cards (one less than in the box set, as requested by the game author)
* 3 'Rock fall' cards
* 28 'Gold' cards
** 16 with one gold nugget
** 8 with two gold nuggets
** 4 with three gold nuggets
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
'''Have a good game !'''
a4923cb01ed4c3387797dd7d0f2a746908e8ed39
83
82
2012-03-11T18:31:04Z
Een
3
/* Available variants */
wikitext
text/x-wiki
== Goal ==
Get as many gold nuggets as possible during the three rounds of the game.
In order to do so,
# if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards
# if you are a '''saboteur''', you must, in association with other gold diggers, prevent the gold diggers to get to the treasure.
Your role (gold digger or saboteur) will be randomly selected at the start of each round.
== Rules summary ==
On your turn, you must click on a card from your hand to select it, then play this card or discard it.
You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card.
The cards are of several types:
* 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card.
* 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score).
* 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you.
* 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about.
* 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove.
== Cards in play ==
* 44 'Path' cards
* 9 'Sabotage' cards (three for each tool)
* 6 'Repair a tool' cards (two for each tool)
* 3 'Repair a tool among these two' cards (one for each combination of two tools)
* 5 'Map' cards (one less than in the box set, as requested by the game author)
* 3 'Rock fall' cards
* 28 'Gold' cards
** 16 with one gold nugget
** 8 with two gold nuggets
** 4 with three gold nuggets
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
89f9a450f60ec687725cea1fef28dabb34a1dc9b
84
83
2012-03-25T17:25:23Z
Coyotek4
143
/* Goal */
wikitext
text/x-wiki
== Goal ==
Get as many gold nuggets as possible during the three rounds of the game.
In order to do so,
# if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards
# if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers to get to the treasure.
Your role (gold digger or saboteur) will be randomly selected at the start of each round.
== Rules summary ==
On your turn, you must click on a card from your hand to select it, then play this card or discard it.
You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card.
The cards are of several types:
* 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card.
* 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score).
* 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you.
* 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about.
* 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove.
== Cards in play ==
* 44 'Path' cards
* 9 'Sabotage' cards (three for each tool)
* 6 'Repair a tool' cards (two for each tool)
* 3 'Repair a tool among these two' cards (one for each combination of two tools)
* 5 'Map' cards (one less than in the box set, as requested by the game author)
* 3 'Rock fall' cards
* 28 'Gold' cards
** 16 with one gold nugget
** 8 with two gold nuggets
** 4 with three gold nuggets
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
aa60b7d77920dffe16a09bc974a9b8de56a45063
85
84
2012-03-25T17:26:37Z
Coyotek4
143
/* Goal */
wikitext
text/x-wiki
== Goal ==
Get as many gold nuggets as possible during the three rounds of the game.
In order to do so,
# if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards
# if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers from getting to the treasure.
Your role (gold digger or saboteur) will be randomly selected at the start of each round.
== Rules summary ==
On your turn, you must click on a card from your hand to select it, then play this card or discard it.
You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card.
The cards are of several types:
* 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card.
* 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score).
* 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you.
* 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about.
* 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove.
== Cards in play ==
* 44 'Path' cards
* 9 'Sabotage' cards (three for each tool)
* 6 'Repair a tool' cards (two for each tool)
* 3 'Repair a tool among these two' cards (one for each combination of two tools)
* 5 'Map' cards (one less than in the box set, as requested by the game author)
* 3 'Rock fall' cards
* 28 'Gold' cards
** 16 with one gold nugget
** 8 with two gold nuggets
** 4 with three gold nuggets
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
ce5786063d5cbea6ae574ca2e25238661377ad54
Gamehelpcoloretto
0
33
86
2012-03-29T15:09:59Z
Greywolf
379
Jokers Rule
wikitext
text/x-wiki
In the regular game, one gets to determine where to place the jokers but apparently for this online version, the jokers are auto-allocated to your highest stacks.
bb7190f77b09c6cf389d7b52c1a18a36bea5403a
Referral
0
11
88
29
2012-04-03T07:31:54Z
Toeeatingdog
468
/* How does this work? */
wikitext
text/x-wiki
[[Category:Help]]
When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]]
== How does this work? ==
Each time a new player creates an account on Board Game Arena from your referral web address(see below), he becomes one of your '''referees'''. As soon as this referee playes 3 games, you become a member of BGA club.
== How to get referees? ==
To recruit referees, use your personal referrer web address:
{sponsorshipurl}
New players MUST create an account from this web address to become one of your referees.
== How to get many referees? ==
* [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook]
* [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter]
* [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email]
* Publish my personal web address in some forum, send it by MSN, ...
== How many BGA club membership days can I win? ==
As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership.
''Note: your account upgrade will be effective within 24 hours.''
As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
... and so on: as your referees number grows you can win many free memberships !
== Referees and multiple account ==
It is of course forbidden to create fake referee accounts to win free memberships.
9099f9116dd4534c68393a2381c254cc0c2afa8a
89
88
2012-04-03T07:32:27Z
Toeeatingdog
468
/* How does this work? */
wikitext
text/x-wiki
[[Category:Help]]
When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]]
== How does this work? ==
Each time a new player creates an account on Board Game Arena from your referrer web address (see below), he becomes one of your '''referees'''. As soon as this referee playes 3 games, you become a member of BGA club.
== How to get referees? ==
To recruit referees, use your personal referrer web address:
{sponsorshipurl}
New players MUST create an account from this web address to become one of your referees.
== How to get many referees? ==
* [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook]
* [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter]
* [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email]
* Publish my personal web address in some forum, send it by MSN, ...
== How many BGA club membership days can I win? ==
As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership.
''Note: your account upgrade will be effective within 24 hours.''
As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
... and so on: as your referees number grows you can win many free memberships !
== Referees and multiple account ==
It is of course forbidden to create fake referee accounts to win free memberships.
63171eacf8f3dcb07c87ea7f365a438d800754c9
90
89
2012-04-03T07:33:42Z
Toeeatingdog
468
/* Referees and multiple account */
wikitext
text/x-wiki
[[Category:Help]]
When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]]
== How does this work? ==
Each time a new player creates an account on Board Game Arena from your referrer web address (see below), he becomes one of your '''referees'''. As soon as this referee playes 3 games, you become a member of BGA club.
== How to get referees? ==
To recruit referees, use your personal referrer web address:
{sponsorshipurl}
New players MUST create an account from this web address to become one of your referees.
== How to get many referees? ==
* [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook]
* [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter]
* [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email]
* Publish my personal web address in some forum, send it by MSN, ...
== How many BGA club membership days can I win? ==
As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership.
''Note: your account upgrade will be effective within 24 hours.''
As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
... and so on: as your referees number grows you can win many free memberships !
== Referees and multiple accounts ==
It is of course forbidden to create fake referee accounts to win free memberships.
aae72040c79a6b18ef8bd1486cd56f5f97eb30d7
Gamehelphawaii
0
34
91
2012-04-04T08:57:29Z
Tobylongbeach
477
Created page with "Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. Th..."
wikitext
text/x-wiki
Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. There are five rounds and you get a decreasing amount of resources each round with which to acquire place tiles. Its a many-paths-to-victory kind of game.
There are three kinds of resources:
1) Feet - let you move around the board, or travel to the islands or go to the cove to catch fish.
2) Clam shells - let you buy place tiles from the board
3) Fruit - can be used in place of feet or clam shells in all-or-nothing fashion. If you substitute for feet, you must substitute the entire moving cost. If you substitute for clams, you must substitute the entire purchase price.
Moving: Your chieftain start at the beach and it costs nothing to return there from the board. Each movement in from the beach costs one foot. Moving up, down, right, left or diagonal on the board costs one foot per space. Staying on a space costs one foot.
To go to the islands, you use your boats and feet. The closest island costs three feet and the farthest costs six. You have to have the feet as well as the space on the boats for the feet. You get an immediate victory point bonus for going to the islands but you do not get a price token (more about that later). Also, you get the level 2 version of whatever place tile or item you are getting on the islands.
For instance, to go to the six foot island, you would need either:
A) two three-feet boats and six feet resources or
B) you would need the four-foot boat (which comes with a prepaid foot) and the two-foot boat as well as five feet resources. That is the advantage of the pre-paid foot on the four-foot boat.
== Purchasing: ==
To buy some thing from the board: Select the price token (round colored circle with number inside) on the space with the place tile or item you want. If there is more than one place tile available on that space, you will be given a choice of which one you want. The movement cost will be in feet and the purchase price will be in clam shells but you can substitute either or both with fruit if you have it. You gain the price token for the round. There must be an available price token in order to purchase something from that space.
You can pay double to get the level 2 version, which for most tiles is double effect.
You place it in the village (row) of your choice. You must be able to place it in order to purchase it.
A) You can only have one of each type of place tile in each village. For instance, you cannot have a foot (1) hut and a foot (2) hut in the same village but you can have a coconut fruit (1) tree and a breadfruit (2) tree in the same village.
B) You can have only one god in each village. You can only have one of each type of god in your whole kingdom and the god vp effects are kingdom-wide.
B) Each village must begin with a hut. The huts have a picture of a hut on them: foot hut, clam hut, spear hut, exchange hut, and long hut.
'''
== Resources ==
'''
== Base reources ==
Base resources are on the round indicator. They decrease with each succeeding round. Everyone gets the base resources at the beginning of the round. Any unused resources can be used in the next round.
== In-play resource bonuses ==
*The third, fourth and fifth villages give you 1, 2 and 3 clams respectively when you purchase Kahunas (Hawaiian priests) for them.
*When you purchase for your kingdom the second, third and fourth Tikis, you are granted 1, 2, and 3 feet, respectively.
*One or two of the island treasures are four fruit resources.
== Resource Generators: == generate resources at the beginning of the next round.
Fruit level ones - one fruit
Fruit level twos - two fruit
Clam hut level one - one clam
Clam hut level two - two clams
Foot hut level one - one foot
Foot hut level two - two feet
Irrigation level two - one resource of your choice
Ku god - level one and two - one foot
Kane god level one - one clam
Kane god level two - two clams
'''== Victory Points =='''
== In-play VP's: ==
*Going to the islands gives you a vp bonus.
*Some of the treasures on the islands are 5 vp's.
*Spear huts and the Ku god give you a bonus whenever you take a price token with crossed spears. Level 1 is 1 pt. bonus, Level 2 is two pt. bonus.
== Round-End VP's: ==
There is a large sheild on the round indicator at the bottom. If the sum of price tokens and fish are greater than the number on the sheild, then you get a bonus. There is a large bonus for the player with highest sum score, a moderate bonus for the second highest and a token bonus for everyone else whose sum was greater than the sheild. Surfer place tiles lower the sheild value for qualifying for the bonus but surfers do not contribute to your sum when comparing to other players.
Lono god level 1 gives you 2 vp's if you qualify for the bonus, and Lono god level 2 gives you 4 vp's if you qualify for the bonus
== Game-End VP's: ==
A) Each village whose size extends to the Tikis and which possesses a Kahuna is active and receives a bonus, listed next to the Kahunas. The first, second, third, fourth and fifth villages receive five, five, ten, ten and fifteen points respectively. Only active villages score points for place tiles in the village.
B) Hula dancer gives you one point for each place tile in her village including herself. Level 2 hula dancer gives you two points instead of one.
C) Irrigation gives you pts for each type of fruit you have in that particular village.
D) Long Hut level 2 is worth five points.
E) Laka god scores one pt for each fruit symbol on your place tiles. Laka god level 2 scores two points for each fruit symbol.
F) Kanaloa god scores two pts for each boat and surfer. Kanaloa 2 scores 4 pts for each boat and surfer.
c7659be503bee1cb94d917358ea72ccc219c822d
Gamehelpcantstop
0
35
92
2012-04-16T17:11:49Z
Iakwvina
538
Created page with "Can't Stop is a very easy and fast game! '''How to play''' You roll 4 dices and then you decide which summaries of 2 dices you want to use.When you do that,you place the tem..."
wikitext
text/x-wiki
Can't Stop is a very easy and fast game!
'''How to play'''
You roll 4 dices and then you decide which summaries of 2 dices you want to use.When you do that,you place the temporary markers on the game board.You are allowed to use 3 temporary markers.These markers are commonly white or black.You continue to roll the dices hoping to bring one of the previous combinations.When you think that it is enough you must say "STOP". Then you replace the white markers with yours.If you roll the dices and there is not possible combination you fail and your progress doesn't be saved.The game board has paths from 2 to 12.The most common are 6,7 and 8 so they have more steps in their paths.
'''The object of the game is''' to reach and cover 3 peeks of these paths!
1c67b4df40a8303ccc8214a7e52670b1f7e4ffbe
93
92
2012-04-17T00:45:02Z
Jleidich
100
wikitext
text/x-wiki
Can't Stop is a very easy and fast game!
'''How to play'''
Roll 4 standard dice and then choose the sums of any 2 dice to advance your position on the board. You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have less.
'''The object of the game is''' to reach and cover 3 peaks of these columns!
a3f0344e922c7148713a1809f6a3e5275412f2f6
Sponsor
0
36
94
2012-04-17T18:31:04Z
Een
3
Redirected page to [[Referral]]
wikitext
text/x-wiki
#REDIRECT [[Referral]]
ad3d24fb99469ddbdfa9c56714b949f98a1e82b8
Gamehelphawaii
0
34
101
91
2012-05-20T18:07:54Z
Tobylongbeach
477
wikitext
text/x-wiki
Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. There are five rounds and you get a decreasing amount of resources each round with which to acquire place tiles. Its a many-paths-to-victory kind of game.
There are three kinds of resources:
1) Feet - let you move around the board, or travel to the islands or go to the cove to catch fish.
2) Clam shells - let you buy place tiles from the board
3) Fruit - can be used in place of feet or clam shells in all-or-nothing fashion. If you substitute for feet, you must substitute the entire moving cost. If you substitute for clams, you must substitute the entire purchase price.
Moving: Your chieftain start at the beach and it costs nothing to return there from the board. Each movement in from the beach costs one foot. Moving up, down, right, left or diagonal on the board costs one foot per space. Staying on a space costs one foot.
To go to the islands, you use your boats and feet. The closest island costs three feet and the farthest costs six. You have to have the feet as well as the space on the boats for the feet. You get an immediate victory point bonus for going to the islands but you do not get a price token (more about that later). Also, you get the level 2 version of whatever place tile or item you are getting on the islands.
For instance, to go to the six foot island, you would need either:
A) two three-feet boats and six feet resources or
B) you would need the four-foot boat (which comes with a prepaid foot) and the two-foot boat as well as five feet resources. That is the advantage of the pre-paid foot on the four-foot boat.
== Purchasing: ==
To buy some thing from the board: Select the price token (round colored circle with number inside) on the space with the place tile or item you want. If there is more than one place tile available on that space, you will be given a choice of which one you want. The movement cost will be in feet and the purchase price will be in clam shells but you can substitute either or both with fruit if you have it. You gain the price token for the round. There must be an available price token in order to purchase something from that space.
You can pay double to get the level 2 version, which for most tiles is double effect.
You place it in the village (row) of your choice. You must be able to place it in order to purchase it.
A) You can only have one of each type of place tile in each village. For instance, you cannot have a foot (1) hut and a foot (2) hut in the same village but you can have a coconut fruit (1) tree and a breadfruit (2) tree in the same village.
B) You can have only one god in each village. You can only have one of each type of god in your whole kingdom and the god vp effects are kingdom-wide.
B) Each village must begin with a hut. The huts have a picture of a hut on them: foot hut, clam hut, spear hut, exchange hut, and long hut.
'''
== Resources ==
'''
== Base reources ==
Base resources are on the round indicator. They decrease with each succeeding round. Everyone gets the base resources at the beginning of the round. Any unused resources can be used in the next round.
== In-play resource bonuses ==
*The third, fourth and fifth villages give you 1, 2 and 3 clams respectively when you purchase Kahunas (Hawaiian priests) for them.
*When you purchase for your kingdom the second, third and fourth Tikis, you are granted 1, 2, and 3 feet, respectively.
*One or two of the island treasures are four fruit resources.
== Resource Generators: == generate resources at the beginning of the next round.
*Fruit level ones - one fruit
*Fruit level twos - two fruit
*Clam hut level one - one clam
*Clam hut level two - two clams
*Foot hut level one - one foot
*Foot hut level two - two feet
*Irrigation level two - one resource of your choice
*Ku god - level one and two - one foot
*Kane god level one - one clam
*Kane god level two - two clams
'''== Victory Points =='''
== In-play VP's: ==
*Going to the islands gives you a vp bonus.
*Some of the treasures on the islands are 5 vp's.
*Spear huts and the Ku god give you a bonus whenever you take a price token with crossed spears. Level 1 is 1 pt. bonus, Level 2 is two pt. bonus.
== Round-End VP's: ==
There is a large sheild on the round indicator at the bottom. If the sum of price tokens and fish are greater than the number on the sheild, then you get a bonus. There is a large bonus for the player with highest sum score, a moderate bonus for the second highest and a token bonus for everyone else whose sum was greater than the sheild. Surfer place tiles lower the sheild value for qualifying for the bonus but surfers do not contribute to your sum when comparing to other players.
Lono god level 1 gives you 2 vp's if you qualify for the bonus, and Lono god level 2 gives you 4 vp's if you qualify for the bonus
== Game-End VP's: ==
A) Each village whose size extends to the Tikis and which possesses a Kahuna is active and receives a bonus, listed next to the Kahunas. The first, second, third, fourth and fifth villages receive five, five, ten, ten and fifteen points respectively. Only active villages score points for place tiles in the village.
B) Hula dancer gives you one point for each place tile in her village including herself. Level 2 hula dancer gives you two points instead of one.
C) Irrigation gives you pts for each type of fruit you have in that particular village.
D) Long Hut level 2 is worth five points.
E) Laka god scores one pt for each fruit symbol on your place tiles. Laka god level 2 scores two points for each fruit symbol.
F) Kanaloa god scores two pts for each boat and surfer. Kanaloa 2 scores 4 pts for each boat and surfer.
a5b2616a703904b9170cd5ac89d2fbd3cbbf94d5
Rating
0
16
102
72
2012-05-26T13:50:59Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you loose a lot points.
* And so on...
== How is my ELO ranking computed ? ==
The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
Let's try to make it simple: the points you win/lose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you lose at the same table, your ranking will decrease a little. And so on ...
In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
== Okay, but I want to know the formula ! ==
At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* Table Level (TL) is the average of ELO ratings of all players at this table.
* The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player).
* The performance (P) of a player is TL+S.
* The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
a6dc048df01d400d3a40159030d500d2c6d0eeb7
103
102
2012-05-26T14:00:10Z
Sourisdudesert
1
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you loose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
Let's try to make it simple: the points you win/lose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you lose at the same table, your ranking will decrease a little. And so on ...
In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
== Okay, but I want to know the formula ! ==
At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* Table Level (TL) is the average of ELO ratings of all players at this table.
* The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player).
* The performance (P) of a player is TL+S.
* The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
35a2f8521b67c643b02c1cfed37ce9bd61ac058e
104
103
2012-05-26T14:04:17Z
Sourisdudesert
1
/* How is my ELO ranking computed ? */
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you loose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
== Okay, but I want to know the formula ! ==
At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* Table Level (TL) is the average of ELO ratings of all players at this table.
* The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player).
* The performance (P) of a player is TL+S.
* The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
e52ee9312119ec37ea571332e9f96cf44c69833b
105
104
2012-05-26T14:04:53Z
Sourisdudesert
1
/* Some advice */
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you loose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
== Okay, but I want to know the formula ! ==
At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* Table Level (TL) is the average of ELO ratings of all players at this table.
* The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player).
* The performance (P) of a player is TL+S.
* The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
e7710d254d0b0589ff5ca25ac485b8c6f3a44bbf
106
105
2012-05-26T14:15:09Z
Sourisdudesert
1
/* How is my ELO ranking computed ? */
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you loose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
ELO system on BGA has some specificity:
* During your first 30 games, your ELO rating is more "elastic": you can win (or loose) more points at each game. This way, your ELO rating converge faster to you "natural" rating.
* Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you loose a 2-player game against each opponent before you (in game rank).
* Games with more than 2 players last longer. For this reason, there's more points to win (or loose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* Table Level (TL) is the average of ELO ratings of all players at this table.
* The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player).
* The performance (P) of a player is TL+S.
* The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
3cd935f80c6c6f00744f005218d18d42bd5e6acf
107
106
2012-05-26T14:18:41Z
Sourisdudesert
1
/* Okay, but I want to know the formula ! */
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you loose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
ELO system on BGA has some specificity:
* During your first 30 games, your ELO rating is more "elastic": you can win (or loose) more points at each game. This way, your ELO rating converge faster to you "natural" rating.
* Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you loose a 2-player game against each opponent before you (in game rank).
* Games with more than 2 players last longer. For this reason, there's more points to win (or loose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly one's used by the ELO rating system, with the following adjustments:
* At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players".
* If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
83d9c1282c8bbed7224adc1193fa6025698360b1
Gamehelpcaylus
0
37
108
2012-06-08T12:16:00Z
Xeno611
648
a fix
wikitext
text/x-wiki
The link above for the rules text is broken, here is the proper one [http://www.ystari.com/caylus/CayUS.pdf Caylus Rule book]
dec8842e16c43a0bdf8306d09cefef9977201436
Gamehelpdiams
0
38
109
2012-06-13T20:56:30Z
Een
3
Created page with " == Goal == Get as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color or more (up to five). Each color has a matchi..."
wikitext
text/x-wiki
== Goal ==
Get as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color or more (up to five).
Each color has a matching value between 1 to 10.
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market
Then you will have to choose between two actions (phase 2):
* Select one of your card and go to the market with this card. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose values sum up to the value of the card you went to the market with
** Come back empty ended
* Select cards in your hand and secure them into your safe. Your selection:
** Must contain at least one collection
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some cards to keep only 5.
== Special cards ==
== Available variants ==
'''Have a good game !'''
c548022931a8d0df231a0d4b6e840d226e525204
110
109
2012-06-13T21:06:55Z
Een
3
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
On each round, you'll earn victory chips based on the points earned collecting diamonds. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is the '7', not the '10')
The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. Your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
== Available variants ==
'''Have a good game !'''
ceb5509a22f4538c3055f3866cc8ebb9dbac81f4
111
110
2012-06-13T21:21:17Z
Een
3
/* Available variants */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
On each round, you'll earn victory chips based on the points earned collecting diamonds. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is the '7', not the '10')
The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. Your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
643d9f4bc5d615656496eb5a5ed70d66cf6da703
112
111
2012-06-13T21:31:05Z
Een
3
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
On each round, you'll earn victory chips based on the points earned collecting diamonds. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is the '7', not the '10')
The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. Your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
''Secur`express'' enables you to secure diamonds of one quality already present in your safe
''Safe drilling'' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
''Sleight of hand'' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
d596468bbd4851645c67eb9a7a0cb676984c0ec6
113
112
2012-06-13T21:32:39Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10')
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. Your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
''Secur`express'' enables you to secure diamonds of one quality already present in your safe
''Safe drilling'' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
''Sleight of hand'' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
43e2f2bf0e3fbfaa319218cfe03ee62cef32271a
114
113
2012-06-13T21:34:02Z
Een
3
/* Rules summary */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10')
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
''Secur`express'' enables you to secure diamonds of one quality already present in your safe
''Safe drilling'' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
''Sleight of hand'' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
695fba417b313f914ffd6c149492f05049def263
115
114
2012-06-13T21:34:25Z
Een
3
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10')
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
19ceabc9061b0a187671c4db40e214f66516dc65
116
115
2012-06-13T21:34:42Z
Een
3
/* Available variants */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10')
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
6131f77032d5baa37874120100912d9bdb56cf75
117
116
2012-06-13T21:37:38Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity in his safe (magnifying glass symbol) and for the player whose diamonds digits in hand sum up to the biggest value.
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
d1b0220c82a08620127520971f823abe8813b2b2
118
117
2012-06-13T21:39:26Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity in his safe (magnifying glass symbol, 5 bonus points, 2 points in case of a tie) and for the player whose diamonds digits in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
868fbcf9a41ea50e24a1a14474160cce69b6733b
119
118
2012-06-13T21:40:34Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
6e0a67b750f9a539b72ac427ef89189b58fd6016
120
119
2012-06-13T21:41:33Z
Een
3
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
e04a679791f79449ec50aa30c74413cf1e5df788
121
120
2012-06-13T21:42:01Z
Een
3
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
5ac6a2422de77758d42de4dc6cb285e50c1d730e
122
121
2012-06-13T21:45:22Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 and so on). The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
e8f0cd0e229a5b47857ebd7b85a02ae1fabc94d4
123
122
2012-06-13T21:45:39Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many diamond collections as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the most victory chips at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
9cfe856cf374159dc625af28fbb99068cc5d0266
124
123
2012-06-13T21:46:29Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two possibilities (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two actions (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
1f43bf7cba2bf5a15119b37f4e4ca3b63e58f395
125
124
2012-06-13T21:47:30Z
Een
3
/* Rules summary */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game !'''
8dbb958af624cfa3ddb5963303e0f8fbfc902997
126
125
2012-06-15T18:53:45Z
Een
3
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
92496c4b6e26fb4f7c997524ee11bcbd1fdf9cd6
127
126
2012-06-15T18:56:45Z
Een
3
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins!
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
39b1f29563cdb81647bdd16d15da8b20442a7718
128
127
2012-06-16T13:46:46Z
Een
3
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
8da68d505b4bab957ec3a8b0c562e040f7ced9dc
129
128
2012-06-18T18:49:28Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching quality digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
7f051d4fe265413fd7537709dbadfe420396ed1f
130
129
2012-06-18T18:51:57Z
Een
3
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching quality digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (please take note however, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
45da0f7bedaf3c9f89202f20840a6bd2d54e5c65
131
130
2012-06-18T18:59:23Z
Een
3
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (please take note however, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
43ea17ba2484b5535f8073731b3d0c7a6eeafffd
132
131
2012-06-18T18:59:56Z
Een
3
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (please take note however that if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
11ee17814253934e13773d95ad05fd1a98616ea9
133
132
2012-06-18T19:00:33Z
Een
3
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (of course, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
f7ae2b1fd802f3d68b779ddba760461388c132dd
134
133
2012-06-18T19:47:14Z
Een
3
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
9a4d8f6b6f72f40fca58395367ce2b205dfd0e11
Gamehelpstoneage
0
21
135
99
2012-06-26T15:37:57Z
Bastan
978
/* Game end */
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, according to civilization cards acquired by you.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings).
Special rules for game with 2 players only:
* no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
Special rules for game with 3 players only:
* no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
===Use the actions of your placed people===
Each player uses all his placed people in any order, and perform the corresponding actions:
* '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* '''field''': increase agriculture level.
* '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded).
* '''hut''': get one additional people.
* '''building card''': buy the building with resources, scoring some points.
* '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied.
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You may use tools to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...).
===Civilization card details===
Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card).
Place the mouse cursor on each card to see details in the tooltip.
Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore.
===Feed your people===
Each agriculture level automatically give you 1 food.
You must provide 1 food per person.
You may use any resource to feed your people if there is not enough food.
If you don't manage to feed your people by means above, you lose 10 points as a penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
Final number of points for each player is summed out of
* points earned during the game by acquiring buildings, minus food penalties,
* multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc).
* each resource that a player has on his player board scores 1 point
a253652bd7e7b7a766518baaba762f793c4fe7f6
Contact us
0
9
136
61
2012-06-27T18:25:25Z
Een
3
wikitext
text/x-wiki
'''Board Game Arena''' is located in France.
== Contact e-mail ==
contact(at)boardgamearena.com
We receive ''a lot'' of e-mails. Please do not send us an e-mail in any of these two cases:
* If you want to report a bug, please do it in the corresponding forum
* If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile.
== Responsible ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
51933312a01a4748b0ec1631205b3a80418dc06d
137
136
2012-06-27T18:29:32Z
Een
3
/* Contact e-mail */
wikitext
text/x-wiki
'''Board Game Arena''' is located in France.
== Contact e-mail ==
contact(at)boardgamearena.com
We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases:
* If you want to report a bug, please do it in the corresponding forum
* If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile.
== Responsible ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
7bf5a90e4b8f025c1ae505fd06cd2eff3a1e50d2
138
137
2012-06-27T18:29:51Z
Een
3
/* Responsible */
wikitext
text/x-wiki
'''Board Game Arena''' is located in France.
== Contact e-mail ==
contact(at)boardgamearena.com
We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases:
* If you want to report a bug, please do it in the corresponding forum
* If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile.
== Administrator ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
62315f21725bfc9363f06b56eb43a553eb505eb1
139
138
2012-06-27T18:31:18Z
Een
3
/* Administrator */
wikitext
text/x-wiki
'''Board Game Arena''' is located in France.
== Contact e-mail ==
contact(at)boardgamearena.com
We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases:
* If you want to report a bug, please do it in the corresponding forum
* If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile.
== Postal address ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
e608e0a52f031694659de3f162e71fd4c20a7fff
Contact
0
39
140
2012-06-27T18:40:51Z
Een
3
Redirected page to [[Contact us]]
wikitext
text/x-wiki
#REDIRECT [[Contact us]]
44227f4a379d1cb9c906fc5923f86e642d717086
Aboutus
0
40
141
2012-06-27T18:42:01Z
Een
3
Redirected page to [[About us]]
wikitext
text/x-wiki
#REDIRECT [[About us]]
bb476bbb3a6b3eb744f44c0fbdfcb920954a6022
Gamehelpraceforthegalaxy
0
41
142
2012-06-28T09:06:10Z
Spacediver
718
Created page with "You may drag a resource (single-coloured small card) to a consumption power to consume it."
wikitext
text/x-wiki
You may drag a resource (single-coloured small card) to a consumption power to consume it.
f221b6292998d419075a2a637383e0b7808e4b7a
143
142
2012-06-30T06:05:24Z
Entropy2k
993
wikitext
text/x-wiki
In Race for the Galaxy, players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods, and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, consuming goods, and bonuses from special developments. There are 5 phases to choose from: explore, develop, settle, consume, and produce. Players pick 1 phase per turn ( two phases in a 2 player game), then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player plays 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
332ed8ac115c5b36871360de512d2523c65ceca7
Gamehelpdragonheart
0
31
144
96
2012-07-14T21:55:41Z
Crazy c
1053
/* Cards */
wikitext
text/x-wiki
==Summary==
Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down.
==Goal==
To have the most points by the end of the game.
==Game Start==
At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board.
==End==
The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 2 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game.
==Turns==
Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship.
==Cards==
There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what.
* ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf.
* ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board.
* ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards.
* ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress.
* ''Troll'': Placing this card allows the player to take the sorceress pile.
* ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board.
* ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent.
* ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon.
* ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn.
* ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand.
cb9673f3d13c9a0f1bbdc1666c6d3f1298f6486f
145
144
2012-07-14T21:57:15Z
Crazy c
1053
/* End */
wikitext
text/x-wiki
==Summary==
Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down.
==Goal==
To have the most points by the end of the game.
==Game Start==
At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board.
==End==
The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game.
==Turns==
Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship.
==Cards==
There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what.
* ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf.
* ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board.
* ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards.
* ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress.
* ''Troll'': Placing this card allows the player to take the sorceress pile.
* ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board.
* ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent.
* ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon.
* ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn.
* ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand.
e984bb914251f4a0f157c7a0785d53b3d4905237
146
145
2012-07-14T21:58:29Z
Crazy c
1053
/* End */
wikitext
text/x-wiki
==Summary==
Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down.
==Goal==
To have the most points by the end of the game.
==Game Start==
At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board.
==End==
The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins.
==Turns==
Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship.
==Cards==
There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what.
* ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf.
* ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board.
* ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards.
* ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress.
* ''Troll'': Placing this card allows the player to take the sorceress pile.
* ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board.
* ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent.
* ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon.
* ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn.
* ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand.
3e0a5f8d9ad58be87706271bf73b4fcc52471ff6
Gamehelptobago
0
27
147
87
2012-07-19T06:49:54Z
Crazy c
1053
/* 2) Move ATV from 1 to 3 legs */
wikitext
text/x-wiki
== Goal ==
Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map indicate where the treasure can be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or only one space when moving from one land type to another.
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
The game ends after the last treasure card has been given out.
'''Have a good game !'''
162a27ee6a534e10c342b291885452d9fdf04053
148
147
2012-07-19T07:09:01Z
Crazy c
1053
/* 1) Play a clue card from his hand */
wikitext
text/x-wiki
== Goal ==
Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that:
*The new clue card mustn't contradicted any present clue cards of the specific treasure map.
*The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything).
*The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board).
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or only one space when moving from one land type to another.
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
The game ends after the last treasure card has been given out.
'''Have a good game !'''
e77ddbfe3be6e45d3526a4e0ace96c704f87d2b8
149
148
2012-07-19T07:10:35Z
Crazy c
1053
/* Goal */
wikitext
text/x-wiki
== Goal ==
Be the player with the most gold coins by locating treasures on the Tobago island and/or sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that:
*The new clue card mustn't contradicted any present clue cards of the specific treasure map.
*The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything).
*The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board).
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or only one space when moving from one land type to another.
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
The game ends after the last treasure card has been given out.
'''Have a good game !'''
1349f4ae9b3bc89321b0a00622234f29a6611878
150
149
2012-07-19T07:22:16Z
Crazy c
1053
/* 2) Move ATV from 1 to 3 legs */
wikitext
text/x-wiki
== Goal ==
Be the player with the most gold coins by locating treasures on the Tobago island and/or sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that:
*The new clue card mustn't contradicted any present clue cards of the specific treasure map.
*The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything).
*The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board).
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or only one space when moving from one land type to another.
===3) Treasure sharing and amulets===
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. Raising a treasure will end a player's turn, even if the player has not used all 3 legs.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
===End of the game===
The game ends after the last treasure card has been given out.
'''Have a good game !'''
3006885193bc285203a8f1e9db8ee4f4e3a7c323
Gamehelptobago
0
27
151
150
2012-07-19T07:28:59Z
Crazy c
1053
/* End of the game */
wikitext
text/x-wiki
== Goal ==
Be the player with the most gold coins by locating treasures on the Tobago island and/or sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that:
*The new clue card mustn't contradicted any present clue cards of the specific treasure map.
*The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything).
*The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board).
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or only one space when moving from one land type to another.
===3) Treasure sharing and amulets===
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. Raising a treasure will end a player's turn, even if the player has not used all 3 legs.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
===End of the game===
The game ends when the treasure card pile runs out.
'''Have a good game !'''
dae010445287c763c8ab4bb06d1c09883e19707b
161
151
2012-08-27T23:39:45Z
Villager
1295
/* 3) Treasure sharing and amulets */
wikitext
text/x-wiki
== Goal ==
Be the player with the most gold coins by locating treasures on the Tobago island and/or sharing them with other players.
== Rules summary ==
On their turn, each player can choose one of two actions:
===1) Play a clue card from his hand===
The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue).
Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of.
When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type.
The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that:
*The new clue card mustn't contradicted any present clue cards of the specific treasure map.
*The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything).
*The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board).
When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be.
When there is only one of these markers left, the treasure is located and can be raised.
===2) Move ATV from 1 to 3 legs===
A leg is a move of:
* either as many spaces as you want in the same land type
* or only one space when moving from one land type to another.
===3) Treasure sharing and amulets===
When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. Raising a treasure will end a player's turn, even if the player has not used all 3 legs.
Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure.
Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards.
An additional card is taken from the deck and the cards are shuffled.
Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded.
Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card.
When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map.
Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base.
Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions:
* play a clue card
* remove a treasure marker
* move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet.. BUT you can RAISE a treasure!)
* to exchange the clue cards from his hand with clue cards from the deck
Proper use of amulet power is critical to ensure victory!
===End of the game===
The game ends when the treasure card pile runs out.
'''Have a good game !'''
953052c0da61d4fc18048a92604e5b53e2e54e84
Gamehelpdiams
0
38
152
134
2012-07-22T09:03:02Z
Crazy c
1053
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
33228376d9a780183c2c7c45fc52dae361572e2d
153
152
2012-07-22T09:04:15Z
Crazy c
1053
/* Special cards */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will lose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
1129c9ce9f9cc7e7d942da196bfc69693fd04ca7
Gamehelpunitedsquare
0
42
154
2012-07-22T09:46:01Z
Crazy c
1053
Created page with "===goal=== The goal is to be the player who has the most squares of his colors. ===rules=== The game contains multicolored squares (red, blue. yellow and green) which appear ..."
wikitext
text/x-wiki
===goal===
The goal is to be the player who has the most squares of his colors.
===rules===
The game contains multicolored squares (red, blue. yellow and green) which appear as 4 colored triangles on the square.
Each player on his turn puts a multicolored square next to a square already on the board. The played square (which can be shifted to fit as requested, keeping the order of the colors the same) must be put in a way that creates at least on colored square (not necessarily your color). If it is not possible for the player to put down a square, the turn is passed to the next player.
It is also possible to have "non playable" squares which are created when 2 of the same color are connected to the same open square. This is also a strategy to prevent from your opponent from getting more squares of his color. (e.g. if there is a red triangle facing an empty square and i connect to that same empty square another red triangle from another side, the empty square cannot be played and all colors around the "non playable" square will not become squares and won't gain points).
===ending the gsme===
When all playable squares have been played, the player with the most squares of his color wins the game.
HAVE A GOOD GAME!
69c010a69b9893a52e587fba072f34ad0c9fbb12
155
154
2012-07-22T09:46:59Z
Crazy c
1053
/* ending the gsme */
wikitext
text/x-wiki
===goal===
The goal is to be the player who has the most squares of his colors.
===rules===
The game contains multicolored squares (red, blue. yellow and green) which appear as 4 colored triangles on the square.
Each player on his turn puts a multicolored square next to a square already on the board. The played square (which can be shifted to fit as requested, keeping the order of the colors the same) must be put in a way that creates at least on colored square (not necessarily your color). If it is not possible for the player to put down a square, the turn is passed to the next player.
It is also possible to have "non playable" squares which are created when 2 of the same color are connected to the same open square. This is also a strategy to prevent from your opponent from getting more squares of his color. (e.g. if there is a red triangle facing an empty square and i connect to that same empty square another red triangle from another side, the empty square cannot be played and all colors around the "non playable" square will not become squares and won't gain points).
===ending the game===
When all playable squares have been played, the player with the most squares of his color wins the game.
HAVE A GOOD GAME!
fc984f3d37b1db341a2475115260c766cf2def67
Gamehelpseasons
0
43
156
2012-08-13T15:53:58Z
Jolelaw
1170
Game help for Season Board Game
wikitext
text/x-wiki
Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be return to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
Star - increase the maximum card player can summon (max 15)
Elements - Gain an energy of the element shown (water, earth, air, fire)
Numbers - Gain the number of Crystals as indicated by the number
Square card - Draw a card
Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at)
Dots - Indicate how fast the marker progress through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
Card summon by other card but due to limitation of the star will cause the new card to be discarded, no refund.
ad8bf0ef8a56d186cb4e1a72485c86c9a94fb6ca
157
156
2012-08-13T15:55:10Z
Jolelaw
1170
wikitext
text/x-wiki
Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be return to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
Star - increase the maximum card player can summon (max 15)
Elements - Gain an energy of the element shown (water, earth, air, fire)
Numbers - Gain the number of Crystals as indicated by the number
Square card - Draw a card
Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at)
Dots - Indicate how fast the marker progress through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
Card summon by other card but due to limitation of the star will cause the new card to be discarded, no refund.
52bce609540fca265df665f782174a6e635e6c51
185
157
2012-09-21T07:54:53Z
Talia
1349
Appending description of the Transmute +1 bonus action.
wikitext
text/x-wiki
Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be return to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
Star - increase the maximum card player can summon (max 15)
Elements - Gain an energy of the element shown (water, earth, air, fire)
Numbers - Gain the number of Crystals as indicated by the number
Square card - Draw a card
Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at)
Dots - Indicate how fast the marker progress through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
Card summon by other card but due to limitation of the star will cause the new card to be discarded, no refund.
aad2a6045db9fb9588409b7c8abd0a0a8e134f43
About us
0
6
158
27
2012-08-15T04:17:28Z
Suds307
1213
wikitext
text/x-wiki
First, we should say that we are gamers. Real, complete boardgames addicts.
We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games.
Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommend you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle).
[[Contact us]]
3df742bb9998193b9edd78eb592b6c63e09eb5fd
Translation guidelines
0
18
159
68
2012-08-19T18:58:42Z
Rokras
1237
/* I fixed some translations, but they don't appear to have changed on the site */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated? ==
Every string of text for the main site interface and for the games' interfaces are 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometime later...
== Who should translate? ==
This is important: only translate text into a given language if you are a native speaker of the language.
When translating a game, the translator should know the game thoroughly and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country.
As Board Game Arena's team's mother tongue is French, we will take charge of the French translations.
We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
39afad37613aa3eedd26702970c7420d0a87fc44
Reputation
0
17
160
73
2012-08-27T02:15:45Z
Villager
1295
/* How to increase my reputation / what makes my reputation decrease ? */
wikitext
text/x-wiki
[[Category:Help]]
== What is reputation ? ==
On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance.
To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items:
* Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png)
* % of games you finished
* % of games you finished with no clock penalties
Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits.
== How to increase my reputation / what makes my reputation decrease ? ==
At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks.
* a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player.
* a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player.
You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change.
As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player.
By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information.
Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up.
== Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png ==
* Be polite ! Say at least "hello" and "good luck" at the beginning of the game. "good game" ("gg") at the end of the game.
* When you need some time to think, click on "I would like to think a little" link.
* Stay calm in any circumstances: it's a game.
* Don't press your opponent to play if he has some time left.
* If you really can't finish the game (this is not supposed to happened...), then say you are sorry and leave the game by your own to save your opponents time.
* Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!).
* Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation.
== What are the consequences of a bad reputation ? ==
A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you.
It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents.
d9004c71be8151f6e6ca1166b60f3f1e209e452c
165
160
2012-09-08T18:11:50Z
Complete muppet
1365
/* Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png */
wikitext
text/x-wiki
[[Category:Help]]
== What is reputation ? ==
On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance.
To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items:
* Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png)
* % of games you finished
* % of games you finished with no clock penalties
Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits.
== How to increase my reputation / what makes my reputation decrease ? ==
At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks.
* a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player.
* a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player.
You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change.
As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player.
By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information.
Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up.
== Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png ==
* Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game.
* When you need some time to think, click on "I would like to think a little" link.
* Always stay calm: it's a game.
* Don't press your opponent to play if he has some time left.
* If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time.
* Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!).
* Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation.
== What are the consequences of a bad reputation ? ==
A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you.
It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents.
7dd2d7d9b84788c2193110bb923f60b6b20dec5b
Game clock
0
15
162
34
2012-09-08T18:06:25Z
Complete muppet
1365
/* Time to think */
wikitext
text/x-wiki
[[Category:Help]]
On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves.
Your initial delay at the beginning of a game is most of the time '''3 minutes'''. At each turn, or on specific occasion, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game.
== Time to think ==
Your alloted time to think is displayed on the right of your player's name. When it's your turn to play. This time is also displayed at the top of the web page.
== Game speed ==
Table administrator can make a choice between 4 game speed profile:
* Fast
* Normal
* Slow
* Without time limit
The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing.
Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing.
== Running out of time ==
As soon as you run out of time, you get a clock penalty.
If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ...
== Move time limit ==
In addition to your classical time to think, you have a limited time alloted for each move.
When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you goes over this limit, you become eligible to be expelled from the game.
== "My opponent is too slow" ==
Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his alloted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so.
== "I would like to think a little" ==
If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page.
Thus, your opponents will receive a message and won't be thinking you are away from keyboard.
Clicking on this link is not mandatory, but we encourage its use for courtesy.
5d8716bd998afb9592ab1dc42cf952b41d0cb657
163
162
2012-09-08T18:06:47Z
Complete muppet
1365
/* Time to think */
wikitext
text/x-wiki
[[Category:Help]]
On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves.
Your initial delay at the beginning of a game is most of the time '''3 minutes'''. At each turn, or on specific occasion, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game.
== Time to think ==
Your alloted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page.
== Game speed ==
Table administrator can make a choice between 4 game speed profile:
* Fast
* Normal
* Slow
* Without time limit
The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing.
Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing.
== Running out of time ==
As soon as you run out of time, you get a clock penalty.
If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ...
== Move time limit ==
In addition to your classical time to think, you have a limited time alloted for each move.
When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you goes over this limit, you become eligible to be expelled from the game.
== "My opponent is too slow" ==
Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his alloted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so.
== "I would like to think a little" ==
If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page.
Thus, your opponents will receive a message and won't be thinking you are away from keyboard.
Clicking on this link is not mandatory, but we encourage its use for courtesy.
7995e4abd5d929043908bb375a931bc0fc50a79b
164
163
2012-09-08T18:09:41Z
Complete muppet
1365
wikitext
text/x-wiki
[[Category:Help]]
On '''Board Game Arena''' you are playing "live" (real time). That means you have an allotted delay to play your moves.
Most of the time, your initial delay at the beginning of a game is '''3 minutes'''. During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game.
== Time to think ==
Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page.
== Game speed ==
Table administrator can make a choice between 4 game speed profile:
* Fast
* Normal
* Slow
* Without time limit
The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing.
Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing.
== Running out of time ==
As soon as you run out of time, you get a clock penalty.
If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ...
== Move time limit ==
In addition to your classical time to think, you have a limited time alloted for each move.
When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you go over this limit, you become eligible to be expelled from the game.
== "My opponent is too slow" ==
Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so.
== "I would like to think a little" ==
If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page.
Thus, your opponents will receive a message and won't be thinking you are away from keyboard.
Clicking on this link is not mandatory, but we encourage its use for courtesy.
8e7b80d9cbd9b3f6552a666e0ca9793092c8f5b3
Gamehelpcolorpop
0
44
166
2012-09-08T18:33:11Z
Davejhave
776
Created page with "Select adjacent colored tokens in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens..."
wikitext
text/x-wiki
Select adjacent colored tokens in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as any color.
You must pop all adjacent tokens of the same color.
0a4173a50ab5172c145b15e28e7a9496b9078db5
167
166
2012-09-08T18:47:19Z
Davejhave
776
wikitext
text/x-wiki
Select adjacent colored tokens in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as any color.
Win instantaly by popping all of your secret colored tokens.
You must pop all adjacent tokens of the same color.
17b1fb1d81ac204da6e965e9ebd8afcd310f6572
168
167
2012-09-09T12:32:33Z
Een
3
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva ([http://www.coloradd.net/ ColorADD]).
'''Have a good game!'''
3718a603bfcba24969ed526d679dae1232da348f
169
168
2012-09-09T12:35:06Z
Een
3
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva ([http://www.coloradd.net/ ColorADD]).
'''Have a good game!'''
4b8ed1d1192e2176b1da8b8aa75ef605b7c580d4
171
169
2012-09-12T19:55:55Z
Een
3
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva ([http://www.coloradd.net/code.asp ColorADD]).
'''Have a good game!'''
612b122320e94857a200782521a758ad2c11d445
172
171
2012-09-12T20:00:14Z
Een
3
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD].
'''Have a good game!'''
34a5c561d3d6540c63bcd99833acc93d4ba5e571
174
172
2012-09-13T17:38:36Z
Een
3
/* Game preferences */
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
'''Have a good game!'''
c1faf3ca99a6d1d9fedff47d69fd8f5b5f3a6f10
175
174
2012-09-13T17:46:08Z
Een
3
/* Game preferences */
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
<img alt="Synthesis panel" src="http://en.doc.boardgamearena.com/images/0/0b/ColorADD.jpg" />
'''Have a good game!'''
16f73ad1be3268a2aa7f75f33fc0f84e0fd90b8b
176
175
2012-09-13T17:49:20Z
Een
3
/* Game preferences */
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
'''Have a good game!'''
c1faf3ca99a6d1d9fedff47d69fd8f5b5f3a6f10
179
176
2012-09-13T19:32:14Z
Een
3
/* Game preferences */
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
'''Have a good game!'''
fa6b2c12165602be9a3d3f3d21a480c5460e4f6d
180
179
2012-09-13T19:32:32Z
Een
3
/* Game preferences */
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
'''Have a good game!'''
def489ae3d57eb9d1faf5a66fbb586c277361faa
181
180
2012-09-13T19:33:10Z
Een
3
/* Game preferences */
wikitext
text/x-wiki
== The game ==
Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped.
White tokens can be used as '''any color'''.
Win '''instantly''' by popping all of your secret colored tokens.
You must pop '''all''' adjacent tokens of the same color.
In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins.
== Variants ==
'''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games.
NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD].
Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
'''Have a good game!'''
ee464ecfaa154f5d4bfc530f7fa81ec68dcbea69
Gamehelpcantstop
0
35
170
93
2012-09-10T02:58:19Z
Wmlwmsh
1387
wikitext
text/x-wiki
Can't Stop is a very easy and fast game!
'''How to play'''
Roll 4 standard dice and then choose the sums of any 2 dice to advance your position on the board. You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have less.
'''The object of the game is''' to reach and cover 3 peaks of these columns!
欲罷不能
如何進行遊戲
首先擲出四顆骰子,之後把四顆骰子兩兩分組配成可以搭配的任意數字(2~12),之後選擇其中一種配對執行。
執行時你可以擁有三個暫時的標記物可以作為前進的工具(此回合超過第三個就不能選該組合中的該項數值,但是其中一項可以前進即可選擇,另外一總組合則視同放棄)
重複以上動作直到你覺得這回合你前進已經夠了或是擲出你沒有辦法前進的骰子點數組合則該回合結束
若是自己喊出「夠了」則在現有的暫時標記物的位置換成自己的標記物輪下一人進行
若是因為擲出不能前進的骰子組合則是本回合前進的格數全部作廢依然換下一人進行回合
遊戲中使用的是兩個六面骰,依照組合的出現機率不同,在不同組合上要攻頂的需求步數也不同(例如7就需要最多格,因為他的出現率最高,相對的比較難出現的2.12就只需要短短的三格)
遊戲獲勝條件是其中有一人佔領了三條路線後則遊戲結束,由佔領三條路線的人獲勝
ea154f34371b9cb6ccc214ccbd3593b52dd35281
파일:ColorADD.jpg
6
45
173
2012-09-13T17:36:42Z
Een
3
ColorADD Synthesis Panel
wikitext
text/x-wiki
ColorADD Synthesis Panel
b91230a1bcd980ad210bfef7eda6568197448d37
177
173
2012-09-13T17:53:14Z
Een
3
uploaded a new version of "[[File:ColorADD.jpg]]"
wikitext
text/x-wiki
ColorADD Synthesis Panel
b91230a1bcd980ad210bfef7eda6568197448d37
178
177
2012-09-13T17:55:55Z
Een
3
uploaded a new version of "[[File:ColorADD.jpg]]"
wikitext
text/x-wiki
ColorADD Synthesis Panel
b91230a1bcd980ad210bfef7eda6568197448d37
Rating
0
16
182
107
2012-09-14T13:37:14Z
Anthonyw
1416
/* How many points do I gain / lose for each game ? */
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you lose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
ELO system on BGA has some specificity:
* During your first 30 games, your ELO rating is more "elastic": you can win (or loose) more points at each game. This way, your ELO rating converge faster to you "natural" rating.
* Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you loose a 2-player game against each opponent before you (in game rank).
* Games with more than 2 players last longer. For this reason, there's more points to win (or loose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly one's used by the ELO rating system, with the following adjustments:
* At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players".
* If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
ac5f5c52715ee05bbf2d34ef4e9b941c675c66ba
183
182
2012-09-14T13:38:46Z
Anthonyw
1416
/* How is my ELO ranking computed ? */
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you lose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
ELO system on BGA has some specificity:
* During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating.
* Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank).
* Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly one's used by the ELO rating system, with the following adjustments:
* At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players".
* If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
5b02a5186bab27aa010cb24915cd423d1d4d795c
184
183
2012-09-14T13:39:14Z
Anthonyw
1416
/* Some advice */
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you lose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you lose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
ELO system on BGA has some specificity:
* During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating.
* Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank).
* Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly one's used by the ELO rating system, with the following adjustments:
* At first, when someone left a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players".
* If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
29eee9580bc23d4a4b15f58a2c641902fc4e17bc
The Boss
0
46
186
2012-10-08T03:20:42Z
Surgeonufo
992
Created page with "Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden u..."
wikitext
text/x-wiki
Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each play:
1) May place gangsters on a city; the large gangsters are returned at the end of each round, while the small ones are not. After placing the gangsters, you must have more of them than any opponent.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color.
When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 2 turns. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
bf53f1c840b684fa8d44a92ff430b74457a9ad71
187
186
2012-10-08T03:30:16Z
Surgeonufo
992
wikitext
text/x-wiki
Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player:
1) May place gangsters on a city; the large gangsters are returned at the end of each round, while the small ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color.
When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 2 turns. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
72e05d23ee671ebfc3e694b7701c429bd6adb695
188
187
2012-10-08T03:58:44Z
Surgeonufo
992
wikitext
text/x-wiki
Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player:
1) May place gangsters on a city; the large gangsters are returned at the end of each round, while the small ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color.
When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 2 turns. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
0984ee8026d2b253a4505a17cc83008844ab701f
189
188
2012-10-10T00:35:14Z
Surgeonufo
992
wikitext
text/x-wiki
Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player:
1) May place gangsters on a city; the large gangsters are returned at the end of each round, while the small ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color.
When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
1cd0608a6589ed0b110ea3d8a710fecfac78d2cd
194
189
2012-10-21T16:41:16Z
Zkiller
1253
wikitext
text/x-wiki
Description
== Headline text ==
Each city, except Chicago, has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city.
The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not.
After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color.
When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
7218e79b6f4ffa499d10c3c79258f17d0df6cea1
195
194
2012-10-21T16:41:46Z
Zkiller
1253
wikitext
text/x-wiki
Description
Each city, except Chicago, has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city.
The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not.
After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color.
When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
2d47a12f90977587d13ecf3b85fc415bb6a0e154
196
195
2012-10-21T16:42:15Z
Zkiller
1253
wikitext
text/x-wiki
Description
Each city, except Chicago, has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color.
When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
c999bf38999a5f8e8cb1a90ca507e252c3b2823c
197
196
2012-10-21T16:50:12Z
Zkiller
1253
wikitext
text/x-wiki
Description
Each city, except Chicago, has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
bb04a8cb3402651b892b179ee2ebca895c2383a3
198
197
2012-10-21T16:56:52Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
Be the player with the most money at the end of the game.
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
== Description ==
Each city, except Chicago, has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
432dfa10f670d4f18e73cc081f9ca0c85fa6c5b2
199
198
2012-10-21T16:59:09Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game.
== Description ==
Each city, except Chicago, has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
c19d7496df06f0519437e32618a00b0d1772c5bc
200
199
2012-10-21T17:01:57Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game.
== Description ==
Each city, except Chicago*, has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
Chicago* city:
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
a6efd2dc5d10193fb18c67e46893ebc0795fe90f
Development
0
47
190
2012-10-10T19:53:06Z
Een
3
Created page with "== TODO =="
wikitext
text/x-wiki
== TODO ==
e1ac7bc92296781c3f0c5713f7149c6d5fe6804f
Help
0
4
191
77
2012-10-11T00:52:25Z
Surgeonufo
992
/* Games */
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena]]
** [[About us]]
** [[Club Board Game Arena]]
** [[Contact us]]
=== Detailed help ===
* [[Getting started]]
* [[Referral]]
* [[Browser support]]
* [[Moderation and grades]]
* [[Game clock]]
* [[Rating]]
* [[Reputation]]
* [[Translation guidelines]]
== Games ==
* [[Gamehelphaggis|Haggis]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelpdominion|Dominion]]
* [[Gamehelpyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpunclechesnutstablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelptheboss]]
0174c39e1b6df9275ad2ba8f3ecaf2a6edaadb52
Gamehelpcoloretto
0
33
192
86
2012-10-12T06:06:20Z
Texkill
1265
wikitext
text/x-wiki
While the regular game requires you to decide which piles to score positive/negative and where to place the jokers, this version automates that to give you the highest score possible.
b9d4a44f0c124786a751dca5b76d3352df39041a
Gamehelpraceforthegalaxy
0
41
193
143
2012-10-12T15:13:03Z
Ksasaki
1566
wikitext
text/x-wiki
In Race for the Galaxy, players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods, and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, consuming goods, and bonuses from special developments. There are 5 phases to choose from: explore, develop, settle, consume, and produce. Players pick 1 phase per turn ( two phases in a 2 player game), then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player plays 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
abca15cea5052494619b6d5f1d5ba12ae3d0805c
The Boss
0
46
201
200
2012-10-21T17:03:05Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except *Chicago, has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
*Chicago:
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
68de3fcea9657fd8d02ccb5635c83e6c62065b91
202
201
2012-10-21T17:03:43Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
7d6daad93cb2c130391c731332e7aacde688aad8
203
202
2012-10-21T17:03:59Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
BEGINNER TIPS
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
7c6b37bc7ca7145555d5c1f1ade750f39b1a0a7f
204
203
2012-10-21T17:05:02Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
2a2298bf5bd374e53398e5cfb1215e89d24d339b
205
204
2012-10-21T17:07:02Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
8fd168878a6d30bb8a84c55609644fcef118bdcc
206
205
2012-10-21T17:08:29Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
071d649f531f765999f2a75340a28612fb75676f
207
206
2012-10-21T17:09:08Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
b36f7ba25cf6739be80f8c65b37507f849d68230
208
207
2012-10-21T17:09:22Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points.
This isn't true for Philadelphia which could still send you to jail.
f89411ca7e04c9d264393ef1174ff70d77d55cc7
209
208
2012-10-21T17:09:50Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
ac01719485336c4476e486c5b66a0948146bb834
210
209
2012-10-21T17:13:33Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
15927b932ec12efb6e7c759531bd55c4c47aa256
211
210
2012-10-21T17:15:26Z
Zkiller
1253
/* Description */
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
=== End ===
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
fbb0032ad54b25bf8e79797d9caf16f06c92d337
212
211
2012-10-21T17:16:04Z
Zkiller
1253
/* Description */
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
=== End ===
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
8a2f3be62a5d4dfa60387a18b4294141548a054e
213
212
2012-10-21T17:16:57Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
=== End ===
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
ad560d07ee3da3a29fd361d5f71106e7d7da192c
214
213
2012-10-21T17:17:18Z
Zkiller
1253
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
=== End ===
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
be896aa3e963c564804a2ad2687dd5f142db909b
215
214
2012-10-21T17:18:18Z
Zkiller
1253
/* Description */
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
0ac56904907b213c1616a11bbaa9c40d0d45a0a2
216
215
2012-10-21T17:18:52Z
Zkiller
1253
/* Description */
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
216df9ddb16c37d4791196cf9503d42bd9c7b533
217
216
2012-10-21T18:32:21Z
Zkiller
1253
moved [[Gamehelptheboss]] to [[The Boss]]: changing the temporary name
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
216df9ddb16c37d4791196cf9503d42bd9c7b533
Gamehelptheboss
0
48
218
2012-10-21T18:32:21Z
Zkiller
1253
moved [[Gamehelptheboss]] to [[The Boss]]: changing the temporary name
wikitext
text/x-wiki
#REDIRECT [[The Boss]]
525eb3913da3d347e1fc98bce9e9581c9311dde1
Help
0
4
219
191
2012-10-21T18:34:06Z
Zkiller
1253
/* Games */
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena]]
** [[About us]]
** [[Club Board Game Arena]]
** [[Contact us]]
=== Detailed help ===
* [[Getting started]]
* [[Referral]]
* [[Browser support]]
* [[Moderation and grades]]
* [[Game clock]]
* [[Rating]]
* [[Reputation]]
* [[Translation guidelines]]
== Games ==
* [[Gamehelphaggis|Haggis]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelpdominion|Dominion]]
* [[Gamehelpyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpunclechesnutstablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelptheboss|The Boss]]
c32d04b6feec5c8e94d0443e6936e954d3e3d428
Studio
0
49
220
2012-10-24T20:17:33Z
Sourisdudesert
1
Created page with "'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) S..."
wikitext
text/x-wiki
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
8bebe049b7e073dc301e36218d40bd9907ed708a
222
220
2012-10-24T20:24:57Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
2b9e8a86566104378c88ee21ca98a6dac0bf5b5c
223
222
2012-10-24T20:33:05Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How to develop a board game on BGA Studio? ==
At first, check out these presentations:
== BGA Studio documentation ==
f9da3165f2dbc6f8331cbf2a9e4e2c321388d1d4
224
223
2012-10-24T20:40:16Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How to develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
== BGA Studio documentation ==
e12da43129600f5b6278753f91665ff8dbfccc27
225
224
2012-10-24T20:42:01Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How to develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* The 8 steps to create a board game on Board Game Arena
== BGA Studio documentation ==
5a9d214a8612c2563cbaad4cb5d70f3b7b7141b4
226
225
2012-10-24T20:52:50Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How to develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
== BGA Studio documentation ==
(available soon...)
1bea11654a7ab6eb5b382657f96413c6797ba21e
228
226
2012-11-22T10:28:01Z
Sourisdudesert
1
/* How to develop a board game on BGA Studio? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How to develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
(available soon...)
a51c138b49e90fc4c1382cfe9ce0daf64b17678c
파일:Bga studio small.jpg
6
50
221
2012-10-24T20:24:25Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelpintheyearofthedragon
0
51
227
2012-11-18T22:32:20Z
Salty-horse
1046
Add end-of-round and -game scoring reminders
wikitext
text/x-wiki
=== End-of-round Scoring ===
* 1 point for each palace.
* 1 point For each court lady.
* 1 point For each privilege. (Small privilege = 1 point; Large privilege = 2 points)
=== End-of-game Scoring ===
* 2 points for each person tile.
* For each monk: score [number of Buddhas] x [number of floors] points.
* 1 point for each 3 yuan.
094e726d8bed26a5b54c43e6aa40764bda2b5679
Gamehelphearts
0
52
229
2012-11-22T12:36:19Z
Daleb147
1803
Created page with "Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack. '''Rank''' A (high) to 2 (low). '''Setup''' The entire deck is dealt, giving ..."
wikitext
text/x-wiki
Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack.
'''Rank'''
A (high) to 2 (low).
'''Setup'''
The entire deck is dealt, giving you a hand of 13 cards. After looking at your cards, choose to pass to another player.
The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player on your right, (3rd hand) to the player across the table, (4th hand) no passing. The rotation repeats until the game ends.
'''Tricks'''
After passing cards, the player holding the 2 of clubs leads the first trick.
Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs.
The highest card of the suit led wins the trick. The winner of a trick starts the next trick.
Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.]
There is no trump suit.
'''Scoring'''
At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13.
If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as shooting the moon), that player scores 0 and all other players score -26.
When one or more players reach zero, the game ends. The player with the highest score wins.
'''Variants'''
Normal game is 100 points.
Quick game is 75 points.
c028cf9094219edf61eff451dedac653ab7fd8f2
230
229
2012-11-22T12:38:14Z
Daleb147
1803
wikitext
text/x-wiki
Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack.
'''Rank'''
A (high) to 2 (low).
'''Setup'''
The entire deck is dealt, giving you a hand of 13 cards. After looking at your cards, choose to pass to another player.
The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player on your right, (3rd hand) to the player across the table, (4th hand) no passing. The rotation repeats until the game ends.
'''Tricks'''
After passing cards, the player holding the 2 of clubs leads the first trick.
Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs.
The highest card of the suit led wins the trick. The winner of a trick starts the next trick.
Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.]
There is no trump suit.
'''Scoring'''
At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13.
If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as shooting the moon), that player scores 0 and all other players score -26.
When one or more players reach zero, the game ends. The player with the highest score wins.
'''Variants'''
Normal game is 100 points.
Quick game is 75 points.
c8041d0b7782fad9106ef871a23dc9af7593637e
231
230
2012-11-22T12:39:33Z
Daleb147
1803
wikitext
text/x-wiki
Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack.
'''Rank'''
A (high) to 2 (low).
'''Setup'''
The entire deck is dealt, giving you a hand of 13 cards. After looking at your hand, choose three cards to pass to another player.
The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player on your right, (3rd hand) to the player across the table, (4th hand) no passing. The rotation repeats until the game ends.
'''Tricks'''
After passing cards, the player holding the 2 of clubs leads the first trick.
Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs.
The highest card of the suit led wins the trick. The winner of a trick starts the next trick.
Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.]
There is no trump suit.
'''Scoring'''
At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13.
If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as shooting the moon), that player scores 0 and all other players score -26.
When one or more players reach zero, the game ends. The player with the highest score wins.
'''Variants'''
Normal game is 100 points.
Quick game is 75 points.
24db4367246faacd715235883032541395f40c23
234
231
2012-11-22T23:25:47Z
Daleb147
1803
wikitext
text/x-wiki
Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack.
'''Rank'''
A (high) to 2 (low).
'''Setup'''
The entire deck is dealt, giving you a hand of 13 cards. After looking at your hand, choose three cards to pass to another player.
The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player across the table, (3rd hand) to the player on your right, (4th hand) no passing. The rotation repeats until the game ends.
'''Tricks'''
After passing cards, the player holding the 2 of clubs leads the first trick.
Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs.
The highest card of the suit led wins the trick. The winner of a trick starts the next trick.
Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.]
There is no trump suit.
'''Scoring'''
At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13.
If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as shooting the moon), that player scores 0 and all other players score -26.
When one or more players reach zero, the game ends. The player with the highest score wins.
'''Variants'''
Normal game is 100 points.
Quick game is 75 points.
c134a170f6a54f64352aab39c6d476725b8c269f
Development
0
47
232
190
2012-11-22T19:40:45Z
Een
3
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How to develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
(available soon...)
a51c138b49e90fc4c1382cfe9ce0daf64b17678c
233
232
2012-11-22T19:43:23Z
Een
3
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How to develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
=== What do I get? ===
=== How should I start? ===
=== Other ressources ===
FAQ
Files reference
Framework functions reference
Development forum
a26867be4e544f9a5579183b085ec9ad12fe79fe
235
233
2012-11-23T09:05:14Z
Een
3
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is opened to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How to develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us|BGA contact address].
Please provide the following information:
* developer's user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* developer's real name;
* developer's email address;
* developer's postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions document for developers on BGA Studio joined as an attachment.
We also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
Then, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login and complex password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initiated from our 'emptygame' template, providing the game structure (and comments! and examples!)
Then you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other ressources ===
FAQ
Files reference
Framework functions reference
Development forum
bf764d6703bea2d63e7e6ca0e028982e48cd8292
236
235
2012-11-23T09:10:43Z
Een
3
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* developer's user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* developer's real name;
* developer's email address;
* developer's postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions document for developers on BGA Studio joined as an attachment.
We also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
Then, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login and complex password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initiated from our 'emptygame' template, providing the game structure (and comments! and examples!)
Then you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other ressources ===
[Development FAQ]
[Development files reference]
[Development framework functions reference]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
979e2f97593be050323fa3e481b8ba78467042da
237
236
2012-11-23T09:14:05Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your contact e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
Then, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login and complex password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initiated from our 'emptygame' template, providing the game structure (and comments! and examples!)
Then you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other ressources ===
[Development FAQ]
[Development files reference]
[Development framework functions reference]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
72bf370daa09b9f048a4b31e1b98a5506fa633e6
238
237
2012-11-23T09:15:00Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
Then, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login and complex password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initiated from our 'emptygame' template, providing the game structure (and comments! and examples!)
Then you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other ressources ===
[Development FAQ]
[Development files reference]
[Development framework functions reference]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
cf121fd0e36ab9d557973fb88647af87ee195063
239
238
2012-11-23T09:18:34Z
Een
3
/* Ok, I registered, what do I get? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other ressources ===
[Development FAQ]
[Development files reference]
[Development framework functions reference]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
b6fda90a3132709481751181d2ce8aaff8f4862c
240
239
2012-11-23T09:21:31Z
Een
3
/* Other ressources */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other ressources ===
[[Development FAQ]]
[[Development files reference]]
[[Development functions reference]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
2e858b45e252006334dcd72c76fca2988fe9cf4a
243
240
2012-11-23T09:52:04Z
Een
3
/* Other ressources */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other resources ===
[[Development FAQ]]
[[Development file reference]]
[[Development function reference]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
e47246dabfa0a690d90e5b0629fd2cf3916767d5
248
243
2012-11-24T09:56:14Z
Een
3
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other resources ===
[[Development FAQ]]
[[Development file reference]]
[[Development function reference]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
0c08a29e8f25782d85af7351110d1819061d46b3
249
248
2012-11-24T11:08:45Z
Een
3
/* Other resources */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'ressources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other resources ===
[[Development FAQ]]
[[Development file reference]]
[[Development function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
2653ee87c6344ebf07629f0b3f8249b5f53ad234
250
249
2012-11-24T11:12:59Z
Een
3
/* Ok, I registered, what do I get? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials).
Then start editing files and see what happens! ;)
=== Other resources ===
[[Development FAQ]]
[[Development file reference]]
[[Development function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
6a298e378936e884914ef321723c403658e558f1
Studio FAQ
0
53
241
2012-11-23T09:39:08Z
Een
3
Created page with "This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Us..."
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== I updated the images in the 'img' folder of my game, but they don't show? ==
Please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
245dd42acf9f030324bddb3016b307338c8f8fb1
242
241
2012-11-23T09:48:15Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== I updated the images in the 'img' folder of my game, but they don't show? ==
Please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
b6678b288dddeacf8990a5fb7fb0afa71067c2fd
Studio file reference
0
54
244
2012-11-23T10:53:17Z
Een
3
Created page with " This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This direct..."
wikitext
text/x-wiki
This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment.
=== 'img' directory ===
This directory contains the images for your game:
* game_box.png is displayed on the main site on the game description page and when creating a table (280x280 px)
* game_icon.png is the icon displayed in the lists of games and tables (50x50 px)
* publisher.png is the logo of the publisher of the game, displayed on the game description page (width: 150 px)
* and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance.
=== dbmodel.sql ===
File for creating specific database tables that you will need to persist data during the game (for example a table for cards).
=== gameoptions.inc.php ===
File for describing your game options (= game variants)
=== <gamename>.action.php ===
File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions.
=== <gamename>.css ===
CSS styles specific to your game.
=== <gamename>.game.php ===
This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
=== <gamename>.js ===
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
=== <gamename>.view.php and <gamename>_<gamename>.tpl ===
Files used to set up the page layout ('view') for the game.
=== material.inc.php ===
File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants.
=== states.inc.php ===
This file describes the states your game will iterate over, and the transitions to get from one state to another.
=== stats.inc.php ===
File used to list statistics that you want to update during the game to be presented to players at the end of the game.
bb690d4d6d5bf813de7ac7ae7d19ade7323cecab
Studio function reference
0
55
245
2012-11-23T11:00:23Z
Een
3
Created page with "This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == ; todo ..."
wikitext
text/x-wiki
This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
; todo : todo
== Client side (Javascript functions) ==
; todo : todo
533cc4280a0aee261ba9cca18e0a826f0de47487
Gamehelpdominion
0
29
246
76
2012-11-24T04:02:03Z
Gelvo
1816
wikitext
text/x-wiki
'''Goal'''
Be the player with the most victory points at the end of the game.
'''Ending Condition'''
The ''Province'' stack being depleted, or 3 stacks of cards being depleted.
'''Setup'''
Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand.
'''Overview'''
The A-B-C rule makes it easy to remember the play order. On a player's turn:
A: Action:
The player may play an action card.
Each player is allowed 1 action per turn by default. Certain action cards provide additional actions.
B: Buy:
After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile.
Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys.
C: Cleanup:
After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck.
The game progresses in clockwise order until ending conditions are met.
'''Tie-breaker'''
If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If there is still a tie, all tied players rejoice in a shared victory.
'''Learning About Each Card'''
To learn about each card in Dominion you can go to [http://deckengine.info/dominion/]
199dbbce7742bec95e581d7c67e7d3e6aafed394
247
246
2012-11-24T04:03:28Z
Gelvo
1816
wikitext
text/x-wiki
'''Goal'''
Be the player with the most victory points at the end of the game.
'''Ending Condition'''
The ''Province'' stack being depleted, or 3 stacks of cards being depleted.
'''Setup'''
Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand.
'''Overview'''
The A-B-C rule makes it easy to remember the play order. On a player's turn:
A: Action:
The player may play an action card.
Each player is allowed 1 action per turn by default. Certain action cards provide additional actions.
B: Buy:
After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile.
Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys.
C: Cleanup:
After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck.
The game progresses in clockwise order until ending conditions are met.
'''Tie-breaker'''
If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If there is still a tie, all tied players rejoice in a shared victory.
'''Learning About Each Card'''
To learn about each card in Dominion you can go to Deck Engine[http://deckengine.info/dominion/]
d8bee17613455731e1204adcab26ce10795c6d0b
Studio back-office
0
56
251
2012-11-24T11:38:02Z
Een
3
Created page with "You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access. Here is a list and description of the links and functions in thi..."
wikitext
text/x-wiki
You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access.
Here is a list and description of the links and functions in this back-office.
Click on a menu to display its content.
=== Documentation ===
Contains links to this wiki, the development forum and the bugs forum.
=== Database ===
Contains a link to the Studio database administration tool (PHPMyAdmin).
Your login / password for this tool is the same as for your SFTP access.
=== Sources ===
Contains a form for committing your sources to the BGA repository.
Game name field should contain the name of your game (lower case, no space).
Comment should contain your commit comment describing changes to the code since your last commit.
You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking us) to get a previous version of your code if you need to backtrack.
=== Logs ===
Gives you a web based access to the studio server logs.
; Current table error log
: main log of interest to you while developing, it contains the error logs happening at the table you are currently playing at
; Current table request logs
: this log traces all the actions happening at the table you are currently playing at
; Javascript error log
: this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly.
; Gameserver error log
: this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file.
; HTTP error log
: this log traces the web server errors. This is useful to look at PHP syntax errors and warnings.
Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in.
You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more.
a75366b91b41d11f5f611dee233b0deee2fc46c7
252
251
2012-11-24T11:41:09Z
Een
3
wikitext
text/x-wiki
You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access.
Here is a list and description of the links and functions in this back-office.
Click on a menu to display its content.
=== Documentation ===
Contains links to this wiki, the development forum and the bugs forum.
=== Database ===
Contains a link to the Studio database administration tool (PHPMyAdmin).
Your login / password for this tool is the same as for your SFTP access.
=== Sources ===
Contains a form for committing your sources to the BGA repository.
* Game name field should contain the name of your game (lower case, no space).
* Comment field should contain your commit comment describing changes to the code since your last commit.
You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack.
=== Logs ===
Gives you a web based access to the studio server logs.
; Current table error log
: main log of interest to you while developing, it contains the error happening at the table you are currently playing at.
; Current table request logs
: this log traces all the actions happening at the table you are currently playing at.
; Javascript error log
: this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly.
; Gameserver error log
: this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file.
; HTTP error log
: this log traces the web server errors. This is useful to look at PHP syntax errors and warnings.
Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in.
You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more.
5623b1560a6ae757eaa2f53c2494e6edda3eab19
Tutorial reversi
0
57
253
2012-11-24T13:03:49Z
Sourisdudesert
1
Created page with "blabla"
wikitext
text/x-wiki
blabla
bb21158c733229347bd4e681891e213d94c685be
254
253
2012-11-24T13:09:13Z
Sourisdudesert
1
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
c26a5af8e6828564ab4ee223d229dc54a9b9286d
255
254
2012-11-24T13:14:14Z
Sourisdudesert
1
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
1af09db09aef0c5098f0fa2a17b2ea9068a1de79
256
255
2012-11-24T13:15:59Z
Sourisdudesert
1
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
So, let's upload our board.
f60e6e9884c37a2e73df5b02b3666c9caa1f5154
258
256
2012-11-24T13:27:24Z
Sourisdudesert
1
/* Let it look like Reversi */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a <div> for your board
<nowiki>
<div id="board">
</div>
</nowiki>
664e12899137864d7e95e67481c51c9a053b8da9
259
258
2012-11-24T13:33:03Z
Sourisdudesert
1
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<nowiki>
<div id="board">
</div>
</nowiki>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
b25c53195c653db74860f7375650536de492b023
261
259
2012-11-24T13:34:55Z
Sourisdudesert
1
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<nowiki>
<div id="board">
</div>
</nowiki>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
8bdac21920f65576aeff896481ae1b41e77998bf
262
261
2012-11-24T13:41:58Z
Sourisdudesert
1
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
2aa9b4055aa2b3b3bd8d72e989c3c0d2d8bf7541
263
262
2012-11-24T13:49:19Z
Sourisdudesert
1
/* Make the squares appears */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
e8f724d68a8ff40cf5c1e30ee29a194a91df7e95
264
263
2012-11-24T13:50:24Z
Sourisdudesert
1
/* Make the squares appears */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
9f506bb9b9388809e70f528325323a3ea3820bdc
267
264
2012-11-24T13:57:41Z
Sourisdudesert
1
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Then, let's design some white&black disc tokens with a little bit of CSS
d6c98d457f8c2baf69ddcb3ea2de8566b739ac7d
269
267
2012-11-24T14:00:05Z
Sourisdudesert
1
/* The discs */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Then, let's design some white&black disc tokens with a little bit of CSS
45d86a617f0bcaabd8a2a2e713ff1ddf0d7b6828
270
269
2012-11-24T14:05:02Z
Sourisdudesert
1
/* The discs */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "javascript template".
aea59cd9a0d5a655a1bfc40de5928cb39c07cd42
271
270
2012-11-24T14:15:06Z
Sourisdudesert
1
/* The discs */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
61619f1af84c80d04243ea001a6082b77b3e6dac
272
271
2012-11-24T14:18:04Z
Sourisdudesert
1
/* The discs */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
f476c6f09986a1589113b80bcde9b224e8b37e07
274
272
2012-11-24T14:22:59Z
Sourisdudesert
1
/* The discs */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Note: of course we can't explain how
d9c8d7a3f87db8034e553a1b158b1bdf75e7e4ea
275
274
2012-11-24T14:23:39Z
Sourisdudesert
1
/* Introduction */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Note: of course we can't explain how
109fc90a2a4ccc1e28bfec0b718896f72258b878
276
275
2012-11-24T14:30:01Z
Sourisdudesert
1
/* The database */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game.
== Setup the initial game position ==
Initially, there are 4 tokens on the board (2 white, 2 black).
f3bd28bcc75748f33ef11ca30faa653345b6eba5
277
276
2012-11-24T14:38:27Z
Sourisdudesert
1
/* Setup the initial game position */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
5bd54f607111d419b76ae50aad1bee09b1fce065
278
277
2012-11-24T14:40:11Z
Sourisdudesert
1
/* The database */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
3740876f658f944737528e641e6352ddff6c27f6
280
278
2012-11-24T14:41:02Z
Sourisdudesert
1
/* Setup the initial game position */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
3baeffb6a7a725930a2c768e195a2650f5ae7750
282
280
2012-11-24T14:42:23Z
Sourisdudesert
1
/* Setup the initial game position */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
b54d251dbf8e412c8a606c3625258999a7a14611
283
282
2012-11-24T14:43:09Z
Sourisdudesert
1
/* The database */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
be60f242a3d7610172e71f72d90cdbd0119508ec
284
283
2012-11-24T14:47:37Z
Sourisdudesert
1
/* Setup the initial game position */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
26605e3dcebc2d859057134f2e4a955b9f084d7f
286
284
2012-11-24T14:49:10Z
Sourisdudesert
1
/* The game state machine */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
7f239e145406ed06bd3d5ea48e7abc90f39f58ee
287
286
2012-11-24T14:52:34Z
Sourisdudesert
1
/* The game state machine */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture above, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
45143c8f884d71113786b746e717385e427b1680
289
287
2012-11-24T15:07:07Z
Sourisdudesert
1
/* The game state machine */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture above, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
1d617cd8cd2e69715ffa9220f5d7e7c3070aadbc
290
289
2012-11-24T15:10:37Z
Sourisdudesert
1
/* The rules */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture above, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed move ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above:
3c3e0f3dbdd3a75eea3c82143585d5912b6d1a4e
291
290
2012-11-24T15:10:55Z
Sourisdudesert
1
/* The game state machine */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed move ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above:
ebc5c345f749b004365eda4eef51ebbafd90d7c9
292
291
2012-11-24T15:18:41Z
Sourisdudesert
1
/* Display allowed move */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
1e8642b57da1bb69f6b242f3f05230046dbc9404
294
292
2012-11-24T15:30:07Z
Sourisdudesert
1
/* Display allowed moves */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
84b70487a17c62e442649e14de5f32556560912f
297
294
2012-11-25T10:24:14Z
Sourisdudesert
1
/* Let's play */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
</pre>
</pre>
fd595cb9caea45c80ef81cdcf140310731e6d701
298
297
2012-11-25T10:30:46Z
Sourisdudesert
1
/* Let's play */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
Now
64278699265cc34b9bc9f92c7be45317d9301059
299
298
2012-11-25T10:34:51Z
Sourisdudesert
1
/* Let's play */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appear in the database:
[[File:reversi9.jpg]]
6101cdabac21b0201d459cc1468064208a53397e
파일:Board.jpg
6
58
257
2012-11-24T13:16:48Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Reversi1.jpg
6
59
260
2012-11-24T13:34:17Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Reversi2.jpg
6
60
265
2012-11-24T13:50:36Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
266
265
2012-11-24T13:50:59Z
Sourisdudesert
1
uploaded a new version of "[[File:Reversi2.jpg]]"
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Tokens.png
6
61
268
2012-11-24T13:58:04Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Reversi3.jpg
6
62
273
2012-11-24T14:18:16Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Reversi4.jpg
6
63
279
2012-11-24T14:40:25Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Reversi5.jpg
6
64
281
2012-11-24T14:41:52Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Reversi6.jpg
6
65
285
2012-11-24T14:47:49Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Reversi7.jpg
6
66
288
2012-11-24T14:53:29Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Reversi8.jpg.jpg
6
67
293
2012-11-24T15:18:51Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Development
0
47
295
250
2012-11-24T17:46:44Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games:
* [[Tutorial reversi]]
* [[Tutorial hearts]]
* [[Tutorial xxx ]]
Then start editing files and see what happens! ;)
=== Other resources ===
[[Development FAQ]]
[[Development file reference]]
[[Development function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
eecf066a299c4dc0c3a8e68add20e2673f238869
Studio FAQ
0
53
296
242
2012-11-24T18:17:21Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== I updated the images in the 'img' folder of my game, but they don't show? ==
Please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "go to database" link at the bottom of your game. This link will bring you directly to the database for the current table.
c077ff8abbf540a10b8cb8c5557634d59d5d85ff
파일:Reversi9.jpg
6
68
300
2012-11-25T10:35:06Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Tutorial reversi
0
57
301
299
2012-11-25T10:37:05Z
Sourisdudesert
1
/* Let's play */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
4cd2519b3e4199201ca4dcc3b691f5ca772579af
322
301
2012-11-28T16:39:13Z
Sourisdudesert
1
/* Make the move appears automatically */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
03d8de1fa331667d24bce827ab6b49abd375f329
323
322
2012-11-28T16:43:41Z
Sourisdudesert
1
/* Make the move appears automatically */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on BGA environment: Reversi game.
Before reading this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah.
Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
d69108e07a1157d677d0be32ad3ad5f0bf653860
Studio FAQ
0
53
302
296
2012-11-25T12:38:59Z
Een
3
/* Is there a quick way to access the database for my current table? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== I updated the images in the 'img' folder of my game, but they don't show? ==
Please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
d08951d5aeff9840f161e2f42c60814d94b4a982
314
302
2012-11-27T20:52:20Z
Een
3
moved [[Development FAQ]] to [[Studio FAQ]]
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== I updated the images in the 'img' folder of my game, but they don't show? ==
Please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
d08951d5aeff9840f161e2f42c60814d94b4a982
329
314
2012-11-30T13:13:17Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' )
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
Please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
e6503c44ae66f7402062c4967deadea42a478c0e
330
329
2012-11-30T13:13:43Z
Een
3
/* Is there a special way to declare the strings that must be translated? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
Please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
347ddc92e9e7cbfe28522592fc2550230373ab27
345
330
2012-12-05T19:50:05Z
Een
3
/* I updated the images in the 'img' folder of my game, but they don't show? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that serves to launch the games. The game icon, box and the publisher logo are hosted on the mainsite server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the Studio back office to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
4b25daf1b81ba2f65df3a679e295cb84e26d2a09
346
345
2012-12-05T19:59:56Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that serves to launch the games. The game icon, box and the publisher logo are hosted on the mainsite server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
639042654b8518f33cb968566c4b2a10df9ada31
347
346
2012-12-05T20:01:10Z
Een
3
/* I updated the images in the 'img' folder of my game, but they don't show? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
c08c1dd70f4dc43128232e20b3f7bb9a1a4e9644
Development
0
47
303
295
2012-11-25T16:46:42Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [['terms & conditions' document:BGA_TC_Dev_en.pdf]]. It's really quick, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment and the following sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games:
* [[Tutorial reversi]]
* [[Tutorial hearts]]
* [[Tutorial xxx ]]
Then start editing files and see what happens! ;)
=== Other resources ===
[[Development FAQ]]
[[Development file reference]]
[[Development function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
ea9b6c9329378a3c6087764ef21789fa4045658c
310
303
2012-11-25T21:20:30Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment and the following sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games:
* [[Tutorial reversi]]
* [[Tutorial hearts]]
* [[Tutorial xxx ]]
Then start editing files and see what happens! ;)
=== Other resources ===
[[Development FAQ]]
[[Development file reference]]
[[Development function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
250ad0fb0beb3717c7ba8e705c8e07a5af724385
311
310
2012-11-25T21:22:25Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games:
* [[Tutorial reversi]]
* [[Tutorial hearts]]
* [[Tutorial xxx ]]
Then start editing files and see what happens! ;)
=== Other resources ===
[[Development FAQ]]
[[Development file reference]]
[[Development function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
5af77415355ccf88e63dafcfd73ca902364ca78d
316
311
2012-11-27T20:53:07Z
Een
3
/* Other resources */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== BGA Studio documentation ==
=== How do I register? ===
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
=== Ok, I registered, what do I get? ===
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
=== Great, I'm in! ... How should I start? ===
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games:
* [[Tutorial reversi]]
* [[Tutorial hearts]]
* [[Tutorial xxx ]]
Then start editing files and see what happens! ;)
=== Other resources ===
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
c025722f9ad5f6199ddad7cb28099f0eeee36959
321
316
2012-11-27T20:54:33Z
Een
3
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== How do I register? ==
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek to tutorials for the example games:
* [[Tutorial reversi]]
* [[Tutorial hearts]]
* [[Tutorial xxx ]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
cd840ccedee7bdbbb48175292cdbc187adffda9e
328
321
2012-11-29T23:08:13Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== How do I register? ==
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at tutorials for two example games:
* [[Tutorial reversi]]
* [[Tutorial gomoku ]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
2d04ceb441b20e7d1be485478ad8716df8f72b6a
332
328
2012-11-30T13:50:28Z
Een
3
/* How can I develop a board game on BGA Studio? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at tutorials for two example games:
* [[Tutorial reversi]]
* [[Tutorial gomoku ]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
39257b26b818eda07805de2338e456c3b42df777
333
332
2012-11-30T13:54:00Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
5f43c2d8a01bca25cac35caa417c67c5428ecf07
334
333
2012-11-30T13:54:35Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address].
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
72dc57200d6a3312dadb9ff5d2d1aaa7c3d73e0e
336
334
2012-11-30T14:35:09Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail to studio(at)boardgamearena.com.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
7bd6cd9d30a6adb2837daf46206634e2e087c3cb
337
336
2012-11-30T14:35:27Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at studio(at)boardgamearena.com.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
4bd37a3234a5ff6846a7e6a0a266ea4d532a6874
338
337
2012-11-30T14:35:54Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
0460b4756dc697bb7e2c0313c08d9d41e4365a2b
339
338
2012-11-30T14:57:01Z
Een
3
/* Ok, I registered, what do I get? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
ec37ab7db579bad08c6bd4b2d8944c42f8289445
340
339
2012-11-30T14:57:41Z
Een
3
/* Ok, I registered, what do I get? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
9ed07dc33eb79a958736a93bf3dc10151ecdd400
341
340
2012-11-30T15:03:35Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]!
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
d2385456525acba6606d1944f34d9bac47a0460a
342
341
2012-11-30T15:03:57Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
01f7f2a589a553ea6267d12e68f7b0cd5907a607
344
342
2012-11-30T15:50:47Z
Een
3
Redirected page to [[Studio]]
wikitext
text/x-wiki
#REDIRECT[[Studio]]
75f930ede7d4ad1a62943418c718a02b755fc4d5
Studio function reference
0
55
304
245
2012-11-25T18:37:20Z
Een
3
wikitext
text/x-wiki
This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
=== APP_GameAction class <gamename>.action.php ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
== Client side (Javascript functions) ==
; todo : todo
5a8d76a6197493599d8d3a89cb9447ed0edc7c2b
305
304
2012-11-25T18:57:56Z
Een
3
wikitext
text/x-wiki
This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
== Client side (Javascript functions) ==
; todo : todo
c8e9bb737a440acb0eee50a8b34aa14ef8a13edb
306
305
2012-11-25T19:04:06Z
Een
3
/* Table class (.game.php) */
wikitext
text/x-wiki
This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
== Client side (Javascript functions) ==
; todo : todo
0b01bb492d9f22816dcd327e0def11a3e8abe281
307
306
2012-11-25T19:15:02Z
Een
3
wikitext
text/x-wiki
This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; todo : todo
64a5654f4a93ed215c0270c01cde118163a7664a
308
307
2012-11-25T21:10:34Z
Een
3
/* Client side (Javascript functions) */
wikitext
text/x-wiki
This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.slideToObjectPos( $('token_'+token.token_id), $('cp_background'), x_pix, y_pix, 10 ).play();
; this.isSpectator
; this.player_id
; this.updateCounters(gamedatas.counters)
; this.addTooltipToClass( 'cp_token_icon_color1', _('Green'), '' );
; this.addEventToClass( "cp_token", "onclick", "onClickToken");
; this.isCurrentPlayerActive()
; this.checkAction( 'selectTokens' )
; this.showMessage( _('You must select at least two tokens'), 'error' );
; this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
; this.updateCounters(notif.args.counters);
; this.ajaxcall( "/colorpop/colorpop/endgame.html", { }, this, function( result ) {} );
b8930b0747d4b187b304b90ae7bc63c4996b456f
317
308
2012-11-27T20:53:20Z
Een
3
moved [[Development function reference]] to [[Studio function reference]]
wikitext
text/x-wiki
This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.slideToObjectPos( $('token_'+token.token_id), $('cp_background'), x_pix, y_pix, 10 ).play();
; this.isSpectator
; this.player_id
; this.updateCounters(gamedatas.counters)
; this.addTooltipToClass( 'cp_token_icon_color1', _('Green'), '' );
; this.addEventToClass( "cp_token", "onclick", "onClickToken");
; this.isCurrentPlayerActive()
; this.checkAction( 'selectTokens' )
; this.showMessage( _('You must select at least two tokens'), 'error' );
; this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
; this.updateCounters(notif.args.counters);
; this.ajaxcall( "/colorpop/colorpop/endgame.html", { }, this, function( result ) {} );
b8930b0747d4b187b304b90ae7bc63c4996b456f
324
317
2012-11-29T22:47:37Z
Een
3
/* Client side (Javascript functions) */
wikitext
text/x-wiki
This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on which browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
; 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; this.addEventToClass( "cp_token", "onclick", "onClickToken");
; this.isCurrentPlayerActive()
; this.checkAction( 'selectTokens' )
; this.showMessage( _('You must select at least two tokens'), 'error' );
; this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
; this.updateCounters(notif.args.counters);
; this.ajaxcall( "/colorpop/colorpop/endgame.html", { }, this, function( result ) {} );
2883f9c0abb0ad4818ba23199536621e31463a82
325
324
2012-11-29T23:04:27Z
Een
3
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
; 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
196b47f3b6d139d77a359829cbfa749061bc3d73
326
325
2012-11-29T23:06:57Z
Een
3
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below.
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
; 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
3cbe8ea5ebf585d8ace0752c8030f718dd2fe28b
327
326
2012-11-29T23:07:06Z
Een
3
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below.
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
; 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
55c96307b77bd59db8d1da2247aa971adf57c54a
파일:BGA TC Dev en.pdf
6
69
309
2012-11-25T21:17:46Z
Een
3
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
331
309
2012-11-30T13:33:17Z
Een
3
uploaded a new version of "[[File:BGA TC Dev en.pdf]]"
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Studio back-office
0
56
312
252
2012-11-27T20:50:47Z
Een
3
wikitext
text/x-wiki
You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access.
Here is a list and description of the links and functions in this back-office.
Click on a menu to display its content.
=== Documentation ===
Contains links to this wiki, the development forum and the bugs forum.
=== Database ===
Contains a link to the Studio database administration tool (PHPMyAdmin).
Your login / password for this tool is the same as for your SFTP access.
=== Sources ===
Contains a form for committing your sources to the BGA repository.
* Game name field should contain the name of your game (lower case, no space).
* Comment field should contain your commit comment describing changes to the code since your last commit.
You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack.
=== Logs ===
Gives you a web based access to the studio server logs.
; Current table error log
: main log of interest to you while developing, it contains the error happening at the table you are currently playing at.
; Current table request logs
: this log traces all the actions happening at the table you are currently playing at.
; Javascript error log
: this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly.
; Gameserver error log
: this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file.
; HTTP error log
: this log traces the web server errors. This is useful to look at PHP syntax errors and warnings.
Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in.
You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more.
b8dac291fbe5b8e2412fc015dff9c7f432d8bd59
313
312
2012-11-27T20:51:22Z
Een
3
wikitext
text/x-wiki
You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access.
Here is a list and description of the links and functions in this back-office.
Click on a menu to display its content.
=== Documentation ===
Contains links to this wiki, the development forum and the bugs forum.
=== Database ===
Contains a link to the Studio database administration tool (PHPMyAdmin).
Your login / password for this tool is the same as for your SFTP access.
=== Sources ===
Contains a form for committing your sources to the BGA repository.
* Game name field should contain the name of your game (lower case, no space).
* Comment field should contain your commit comment describing changes to the code since your last commit.
You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack.
=== Logs ===
Gives you a web based access to the studio server logs.
; Current table error log
: main log of interest to you while developing, it contains the error happening at the table you are currently playing at.
; Current table request logs
: this log traces all the actions happening at the table you are currently playing at.
; Javascript error log
: this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly.
; Gameserver error log
: this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file.
; HTTP error log
: this log traces the web server errors. This is useful to look at PHP syntax errors and warnings.
Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in.
You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more.
cdb10c7884bbf321c65a6abd52427eee6870b1b3
Development FAQ
0
70
315
2012-11-27T20:52:20Z
Een
3
moved [[Development FAQ]] to [[Studio FAQ]]
wikitext
text/x-wiki
#REDIRECT [[Studio FAQ]]
0e0d928fd9ebb07aa5cabcbcb800036357516c70
Development function reference
0
71
318
2012-11-27T20:53:20Z
Een
3
moved [[Development function reference]] to [[Studio function reference]]
wikitext
text/x-wiki
#REDIRECT [[Studio function reference]]
0d4e31ae78128f335e8e652b8bd209497bea7540
Studio file reference
0
54
319
244
2012-11-27T20:53:33Z
Een
3
moved [[Development file reference]] to [[Studio file reference]]
wikitext
text/x-wiki
This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment.
=== 'img' directory ===
This directory contains the images for your game:
* game_box.png is displayed on the main site on the game description page and when creating a table (280x280 px)
* game_icon.png is the icon displayed in the lists of games and tables (50x50 px)
* publisher.png is the logo of the publisher of the game, displayed on the game description page (width: 150 px)
* and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance.
=== dbmodel.sql ===
File for creating specific database tables that you will need to persist data during the game (for example a table for cards).
=== gameoptions.inc.php ===
File for describing your game options (= game variants)
=== <gamename>.action.php ===
File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions.
=== <gamename>.css ===
CSS styles specific to your game.
=== <gamename>.game.php ===
This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
=== <gamename>.js ===
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
=== <gamename>.view.php and <gamename>_<gamename>.tpl ===
Files used to set up the page layout ('view') for the game.
=== material.inc.php ===
File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants.
=== states.inc.php ===
This file describes the states your game will iterate over, and the transitions to get from one state to another.
=== stats.inc.php ===
File used to list statistics that you want to update during the game to be presented to players at the end of the game.
bb690d4d6d5bf813de7ac7ae7d19ade7323cecab
Development file reference
0
72
320
2012-11-27T20:53:33Z
Een
3
moved [[Development file reference]] to [[Studio file reference]]
wikitext
text/x-wiki
#REDIRECT [[Studio file reference]]
7e0b4170c41b68fcf9b09724d3d1b7bf8de5a76e
Tutorial gomoku
0
73
335
2012-11-30T13:56:04Z
Een
3
Created page with "TODO"
wikitext
text/x-wiki
TODO
b698c11e84460ed5999bfeb5cbf25b865c238f3c
Studio
0
49
343
228
2012-11-30T15:49:04Z
Een
3
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at this tutorial for creating the Reversi example game:
* [[Tutorial reversi]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
01f7f2a589a553ea6267d12e68f7b0cd5907a607
파일:Gomoku tuto1.png
6
74
348
2012-12-05T21:06:58Z
Een
3
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Gomoku tuto2.png
6
75
349
2012-12-05T21:07:10Z
Een
3
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Gomoku tuto3.png
6
76
350
2012-12-05T21:07:19Z
Een
3
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Gomoku tuto4.png
6
77
351
2012-12-05T21:07:29Z
Een
3
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Gomoku tuto5.png
6
78
352
2012-12-05T21:07:38Z
Een
3
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Gomoku tuto6.png
6
79
353
2012-12-05T21:07:49Z
Een
3
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Tutorial gomoku
0
73
354
335
2012-12-05T21:09:23Z
Een
3
wikitext
text/x-wiki
Here is how your games look by default when it has just been created :
[[File:Gomoku tuto1.png]]
Gather useful images for the game and edit them as needed.
Edit .tpl & .css to add the board :
[[File:Gomoku tuto2.png]]
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action.
Add game action in .game.php to update the database, then notify the client using a method ‘’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones.
[[File:Gomoku tuto4.png]]
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
Implement specific rules for the game (if any)
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
Test everything thoroughly... you are done!
[[File:Gomoku tuto6.png]]
fcf0d63e99019e009a64cc2f45a3061e0997cdd4
355
354
2012-12-05T21:14:00Z
Een
3
wikitext
text/x-wiki
== Start from the emtpy game template ==
Here is how your games look by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed.
Edit .tpl & .css to add the board :
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action.
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game condition(s) ==
Implement specific rules for the game (if any)
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
Test everything thoroughly... you are done!
[[File:Gomoku tuto6.png]]
770a1936ddb073d24fc46111d83b4de2f07be7e9
356
355
2012-12-05T21:14:15Z
Een
3
/* Start from the emtpy game template */
wikitext
text/x-wiki
== Start from the emtpy game template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed.
Edit .tpl & .css to add the board :
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action.
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game condition(s) ==
Implement specific rules for the game (if any)
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
Test everything thoroughly... you are done!
[[File:Gomoku tuto6.png]]
e4b849c06439e1657646ff876b0611ecc4b37c58
357
356
2012-12-05T21:17:54Z
Een
3
wikitext
text/x-wiki
== Start from the emtpy game template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed.
Edit .tpl to add some div for the board in the HTML.
Edit .css to show the image of the board as background.
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in
material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game condition(s) ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
5459b575222bb6886bbc92e33b2526c342c0f163
358
357
2012-12-05T21:18:27Z
Een
3
/* Setup the board */
wikitext
text/x-wiki
== Start from the emtpy game template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some div for the board in the HTML.
Edit .css to show the image of the board as background.
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in
material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game condition(s) ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
333f80b42a2a4503200c1d2594d04917358be984
359
358
2012-12-05T21:24:48Z
Een
3
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== Start from the emtpy game template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some div for the board in the HTML.
Edit .css to show the image of the board as background.
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in
material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game condition(s) ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
9eb647a35af1b562d14557cf16d235693d35e22b
360
359
2012-12-05T21:25:33Z
Een
3
/* Start from the emtpy game template */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some div for the board in the HTML.
Edit .css to show the image of the board as background.
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in
material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game condition(s) ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
5a68b325ce531060787304be7f314dfe7510e33e
361
360
2012-12-05T21:26:10Z
Een
3
/* Cleanup */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some div for the board in the HTML.
Edit .css to show the image of the board as background.
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in
material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game condition(s) ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
994f40b68cfbaccf00b4bea0f7b2483b6370095e
362
361
2012-12-05T21:26:20Z
Een
3
/* Implement rules and end of game condition(s) */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some div for the board in the HTML.
Edit .css to show the image of the board as background.
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in
material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
812c4fea187e9a853f3dcbd0588770c7c11c1065
364
362
2012-12-05T21:58:44Z
Een
3
/* Setup the board */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections.
Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database.
Edit .game.php->getAllDatas to retrieve the state of the intersections from the database.
Edit .tpl to create a template for intersections (jstpl_intersection).
Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in
material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning.
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
c0758d7154977a6725932786631d490d8a63eaba
365
364
2012-12-05T22:13:33Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit .sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
And pass them to your gomoku.js through gomoku.game.php->getAllDatas() for easy repositioning (modify constant, refresh).
// Constants
$result['constants'] = $this->gameConstants;
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
26ac9382325c962f7620ffdf4174e385a7ee1023
366
365
2012-12-05T22:13:56Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
And pass them to your gomoku.js through gomoku.game.php->getAllDatas() for easy repositioning (modify constant, refresh).
// Constants
$result['constants'] = $this->gameConstants;
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
842acc557f3052d95e38808148093d8e057a3a76
367
366
2012-12-05T22:18:34Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
And pass them to your gomoku.js for easy repositioning (modify constant, refresh).
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
a4b0f28f38a333e965030c81d36ed6b23dea298f
368
367
2012-12-05T22:20:55Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constant values have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
89de825d4f23bd359ed656f28be811507ee532a8
369
368
2012-12-05T22:21:30Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php
Add onclick events on intersections in .js, calling an action with appropriate parameters
Add action in .action.php, retrieving parameters and calling the appropriate game action
Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
The basic game turn is implemented: you can drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
05743b8feac3d4829fc79918f260e21ad40b936d
370
369
2012-12-05T22:36:37Z
Een
3
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
For this function, you need to declare a stone javascript template in your .tpl file
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
2b3fc4e1c8667563a2f5381b7c87a523442c89d4
371
370
2012-12-05T22:40:51Z
Een
3
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
* to define the css styles for the stones
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
These styles rely on an image of both the white and black stones, and position the background appropriately to show only the part of the background image matching the appropriate stone.
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
b4fe94be1cfe6d346bb1587062e3544b3bd7e297
373
371
2012-12-05T22:45:13Z
Een
3
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an image of both the white and black stones, and position the background appropriately to show only the part of the background image matching the appropriate stone or the white space if there is no stone. Here is what the image looks like (we will use the red circle later on):
[[File:Gomoku stones.png]]
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
704504582a9dcb58e10995b39556b6e30a037514
374
373
2012-12-05T22:48:00Z
Een
3
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like (we will use the red circle later on):
[[File:Gomoku stones.png]]
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
d5c4971530420428f040193ef825f9854005ff6e
375
374
2012-12-05T22:55:18Z
Een
3
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game (if any)
Nothing special for Gomoku
Implement rule for computing game progression in .game.php->getGameProgression()
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
779b1978f9b35636690f0a59f27ce681c331b559
377
375
2012-12-05T23:06:25Z
Een
3
/* Implement rules and end of game conditions */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame()
Notify the score and implement the corresponding interface update in .js
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
43b1670c24100dd1aa9409735a8497555c99d047
393
377
2012-12-06T22:07:37Z
Een
3
/* Implement rules and end of game conditions */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner in gomoku.game.php->stCheckEndOfGame()
* It is easier to check for a win directly after setting the stone, so:
** we declare a global 'end_of_game' variable in gomoku.game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
** we init that global variable to 0 in gomoku.game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
** we add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function that we implement separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() which is called when your state machine goes to the 'checkEndOfGame' state, you check for this variable and for other 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* We catch the score notification on the client side in gomoku.js->setupNotifications() and we set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* We implement the function declared to handle the notification.
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
b15b86e48944c4f923af7ef297aa6a697eeeb1d3
394
393
2012-12-06T22:09:13Z
Een
3
/* Implement rules and end of game conditions */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* we declare a global 'end_of_game' variable in gomoku.game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in gomoku.game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* we add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function that we implement separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() which is called when your state machine goes to the 'checkEndOfGame' state, you check for this variable and for other 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* We catch the score notification on the client side in gomoku.js->setupNotifications() and we set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* We implement the function declared to handle the notification.
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
44aa0b4f13643a40db740d0e30d5fba5828e6493
395
394
2012-12-06T22:10:32Z
Een
3
/* Implement rules and end of game conditions */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* we declare a global 'end_of_game' variable in gomoku.game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in gomoku.game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* we add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function that we implement separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, you check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* We catch the score notification on the client side in gomoku.js->setupNotifications() and we set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* We implement the function declared to handle the notification.
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
52031b9a65d85144687c385bb98224a18b1c90ae
396
395
2012-12-06T22:12:25Z
Een
3
/* Implement rules and end of game conditions */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in gomoku.game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in gomoku.game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in gomoku.js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
77087421e739e44ab260cdb86601e5a2c38b6915
397
396
2012-12-06T22:15:10Z
Een
3
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML.
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in gomoku.game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in gomoku.game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in gomoku.game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in gomoku.js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
e369ecff0c1d3a7db33d7af073473f038c059ff9
398
397
2012-12-06T22:16:01Z
Een
3
/* Setup the board */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections (jstpl_intersection).
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in gomoku.game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in gomoku.game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in gomoku.game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in gomoku.js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
2a35d8692c6958f159f309735364afa225f17b63
399
398
2012-12-06T22:17:16Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In gomoku.game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In gomoku.js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in gomoku.game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in gomoku.js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in gomoku.game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in gomoku.game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in gomoku.js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
bfb8e63de4f2e6318889b6e22a427809c8949c3c
400
399
2012-12-06T22:19:30Z
Een
3
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created :
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
54ee41a684ba1db25a6c94e6715491f67ca872f8
Studio FAQ
0
53
363
347
2012-12-05T21:45:22Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
cb1693b12ae4ed239fcfaa093165d65ff0849426
390
363
2012-12-06T21:43:08Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
49c74b0ae1da806be0026784581066e1b1ae1b64
파일:Gomoku stones.png
6
80
372
2012-12-05T22:45:06Z
Een
3
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Tutorial reversi
0
57
376
323
2012-12-05T23:05:05Z
Pikiou
1872
Typos
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
5735d4c608381a182395d0aeed7517711422fc58
378
376
2012-12-05T23:10:00Z
Pikiou
1872
Buggy code result of mixing the words disc and token
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${xy}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
xy: x+''+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
c86f6bd8839862875261fc3c1f99193e43decdc8
379
378
2012-12-05T23:11:55Z
Pikiou
1872
Buggy code because of a missing underscore between x and y
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we active the first player to make it active at the beginning of the game.
Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute.
The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
e10e837e5c2636c2340994157b3085c572f3e307
380
379
2012-12-06T00:36:07Z
Pikiou
1872
/* Setup the initial game position */ Typos
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
5c64283860e84e2f59acc0cd203849a21a95e15b
381
380
2012-12-06T01:12:25Z
Pikiou
1872
/* Setup the initial game position */ $blackplayer_id and $whiteplayer_id weren't defined
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
97a7cd5873575fc05bf2f8f58afb59ef3699ee58
382
381
2012-12-06T01:20:35Z
Pikiou
1872
/* The discs */ Set player colors to white and black
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in our reversi.game.php file the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
1506c28901430d0ff115464f36c7b1e6868aa63f
383
382
2012-12-06T02:07:54Z
Pikiou
1872
/* The game state machine */ Typos
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it.
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
798fcf2511667129243ba3665423ad2815dbad92
384
383
2012-12-06T12:08:18Z
Pikiou
1872
/* Display allowed moves */ Missing the possibleMove class CSS declaration
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square.
Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
39ed1b8df7b3fc58dc4c7a6c1fe1286413cab9bc
385
384
2012-12-06T12:11:08Z
Pikiou
1872
/* Display allowed moves */ Typos
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 56px;
height: 56px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
fe70922d87a5d2f33217e98ae8fb82131665a115
386
385
2012-12-06T12:28:33Z
Pikiou
1872
/* Make the squares appears */ Squares didn't fill their space
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* On server side, check the move is correct, apply Reversi rules and jump to next player.
* On client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Active next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
37dba66a4ed6f61ec2a854bcc3923bbe996220a7
387
386
2012-12-06T15:30:58Z
Pikiou
1872
/* Let's play */ Typos
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* Server side, check the move is correct, apply Reversi rules and jump to next player.
* Client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$player_id = self::getActivePlayerId();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Activate next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
156ea2f58083036772ef8343548e257ae8345b4a
388
387
2012-12-06T15:32:18Z
Pikiou
1872
/* Let's play */ Need to initialize statistics
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* Server side, check the move is correct, apply Reversi rules and jump to next player.
* Client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$player_id = self::getActivePlayerId();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
To make the statistics work, we have to initialize them in state.inc.php:
<pre>
// Statistics existing for each player
"player" => array(
"discPlayedOnCorner" => array( "id"=> 10,
"name" => totranslate("Discs played on a corner"),
"type" => "int" ),
"discPlayedOnBorder" => array( "id"=> 11,
"name" => totranslate("Discs played on a border"),
"type" => "int" ),
"discPlayedOnCenter" => array( "id"=> 12,
"name" => totranslate("Discs played on board center part"),
"type" => "int" ),
"turnedOver" => array( "id"=> 13,
"name" => totranslate("Number of discs turned over"),
"type" => "int" )
)
</pre>
A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Activate next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appears automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handle the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Made these discs blinking and set them to the specified color
for( var i in notif.args.turnedOver )
{
var disc = notif.args.turnedOver[ i ];
// Make the disc blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ),
dojo.fadeOut( {
node: 'disc_'+disc.x+''+disc.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'disccolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
0618aa74ff1170f381a45a8f753790836619cea2
389
388
2012-12-06T16:33:49Z
Pikiou
1872
/* Make the move appears automatically */ Typos
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "stats.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* Server side, check the move is correct, apply Reversi rules and jump to next player.
* Client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$player_id = self::getActivePlayerId();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
To make the statistics work, we have to initialize them in state.inc.php:
<pre>
// Statistics existing for each player
"player" => array(
"discPlayedOnCorner" => array( "id"=> 10,
"name" => totranslate("Discs played on a corner"),
"type" => "int" ),
"discPlayedOnBorder" => array( "id"=> 11,
"name" => totranslate("Discs played on a border"),
"type" => "int" ),
"discPlayedOnCenter" => array( "id"=> 12,
"name" => totranslate("Discs played on board center part"),
"type" => "int" ),
"turnedOver" => array( "id"=> 13,
"name" => totranslate("Number of discs turned over"),
"type" => "int" )
)
</pre>
A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Activate next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appear automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handles the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Make these discs blink and set them to the specified color
for( var i in notif.args.turnedOver )
{
var token = notif.args.turnedOver[ i ];
// Make the token blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeOut( {
node: 'token_'+token.x+'_'+token.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'tokencolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
9bf25b0bffa92efc21acecec6a36e5d946859991
Studio back-office
0
56
391
313
2012-12-06T21:43:49Z
Een
3
/* Sources */
wikitext
text/x-wiki
You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access.
Here is a list and description of the links and functions in this back-office.
Click on a menu to display its content.
=== Documentation ===
Contains links to this wiki, the development forum and the bugs forum.
=== Database ===
Contains a link to the Studio database administration tool (PHPMyAdmin).
Your login / password for this tool is the same as for your SFTP access.
=== Sources ===
Contains a form for committing your sources to the BGA repository.
* Game name field should contain the name of your game (lower case, no space). Ex: puertorico
* Comment field should contain your commit comment describing changes to the code since your last commit.
You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack.
=== Logs ===
Gives you a web based access to the studio server logs.
; Current table error log
: main log of interest to you while developing, it contains the error happening at the table you are currently playing at.
; Current table request logs
: this log traces all the actions happening at the table you are currently playing at.
; Javascript error log
: this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly.
; Gameserver error log
: this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file.
; HTTP error log
: this log traces the web server errors. This is useful to look at PHP syntax errors and warnings.
Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in.
You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more.
b8fd0f6cc336100886af11fe1c0b50fea185e534
Studio function reference
0
55
392
327
2012-12-06T22:06:45Z
Een
3
/* Client side (Javascript functions) */
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below.
== Server side (PHP functions) ==
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
6d38dcd8680be3c28de97befb1efdaa8f385d027
Tutorial gomoku
0
73
401
400
2012-12-06T22:19:41Z
Een
3
/* You will start from our 'emtpy game' template */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
751fd879e8fc20a5a4276b292a84a8fc69aeed72
402
401
2012-12-06T22:21:47Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
87d10ec1ed913f5e43d8a32370d7bda0e373fadf
403
402
2012-12-06T22:22:43Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get after some tweaks and refresh:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
4e63521137d4911761e2ace1450021690f87d429
404
403
2012-12-06T22:23:06Z
Een
3
/* Setup the backbone of your game */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
87d10ec1ed913f5e43d8a32370d7bda0e373fadf
405
404
2012-12-06T22:24:28Z
Een
3
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* we init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
d1f9ba2385a1a391c47d8959c71dba650410cd96
406
405
2012-12-06T22:26:48Z
Een
3
/* Implement rules and end of game conditions */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
aacabbe7efb7c6b91947fe7a33b4e170d580f067
407
406
2012-12-06T22:27:38Z
Een
3
/* Implement rules and end of game conditions */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' );
}));
slide.play();
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
5ffdfba9f0e591c1b7eee1236e59ba7b7ffc2c94
Studio
0
49
408
343
2012-12-06T22:29:11Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
2f629611da109a5f3e8c61e0d395592c19b646ef
409
408
2012-12-07T10:09:19Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
4776ee490903437bd94367e54ca55ff5d0e80636
414
409
2012-12-11T14:48:31Z
Een
3
/* How do I register? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is this? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your player user name on BGA
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
f2d26be5ae879cac19e56ee406d83528b3d57077
428
414
2013-01-05T09:35:34Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== How can I develop a board game on BGA Studio? ==
Check these presentations first:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your player user name on BGA
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
a91516e964e65f1efa5a28e4ab7e4121bf38ea02
429
428
2013-01-05T09:41:36Z
Sourisdudesert
1
/* How can I develop a board game on BGA Studio? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How do I register? ==
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your player user name on BGA
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
dc62fcaa145e23c1d275111856dc5c7d56a8afb7
430
429
2013-01-05T09:46:29Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
aa67d4007c5a725783c814eefd8d15c3745f1878
432
430
2013-01-05T09:47:50Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== Other resources ==
[[Studio FAQ]]
[[Studio file reference]]
[[Studio function reference]]
[[Studio back-office]]
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
e2f3e477cb0aa6465e28ac5c6fbd0159b5cddd76
433
432
2013-01-05T09:55:12Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference]]
[[Studio function reference]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
a08a63f342a76db9ad2d456591e2f4759344c61f
434
433
2013-01-05T09:58:34Z
Sourisdudesert
1
/* BGA Studio Framework reference */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|Files structure of a BGA game]]
[[Studio function reference]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
e6490a1a2089cdb7871765132f3f8d702ac1853c
435
434
2013-01-05T09:59:06Z
Sourisdudesert
1
/* BGA Studio Framework reference */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
[[Studio function reference]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
d3b8d6a65251dce3e3e8ceb78bfa73c42efb0f65
436
435
2013-01-05T10:08:56Z
Sourisdudesert
1
/* BGA Studio Framework reference */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
[[Main game logic (<gamename>.game.php)]]
[[Your game state machine (states.inc.php)]]
[[Game database model (dbmodel.sql)]]
[[Players actions (<gamename>.action.php)]]
[[Game material description (material.inc.php)]]
[[Game statistics (stats.inc.php)]]
==== Game interface ====
[[Game interface logic (<gamename>.js)]]
[[Game art (img directory)]]
[[Game interface stylesheet (<gamename>.css)]]
[[Game layout: view and template (<gamename>.view.php and <gamename>_<gamename>.tpl)]]
==== Other components ===
[[Game options and preferences (gameoptions.inc.php)]]
[[Studio function reference]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
f40cffdcec66a058431e166fc222e144c5b19136
437
436
2013-01-05T10:09:07Z
Sourisdudesert
1
/* BGA Studio documentation */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
[[Main game logic (<gamename>.game.php)]]
[[Your game state machine (states.inc.php)]]
[[Game database model (dbmodel.sql)]]
[[Players actions (<gamename>.action.php)]]
[[Game material description (material.inc.php)]]
[[Game statistics (stats.inc.php)]]
==== Game interface ====
[[Game interface logic (<gamename>.js)]]
[[Game art (img directory)]]
[[Game interface stylesheet (<gamename>.css)]]
[[Game layout: view and template (<gamename>.view.php and <gamename>_<gamename>.tpl)]]
==== Other components ====
[[Game options and preferences (gameoptions.inc.php)]]
[[Studio function reference]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
aefa09e482bda70b699e7e2e8febb638d76e4ebc
438
437
2013-01-05T10:10:34Z
Sourisdudesert
1
/* BGA Studio documentation */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic (yourgamename.game.php)]]
* [[Your game state machine (states.inc.php)]]
* [[Game database model (dbmodel.sql)]]
* [[Players actions (yourgamename.action.php)]]
* [[Game material description (material.inc.php)]]
* [[Game statistics (stats.inc.php)]]
==== Game interface ====
* [[Game interface logic (yourgamename.js)]]
* [[Game art (img directory)]]
* [[Game interface stylesheet (yourgamename.css)]]
* [[Game layout: view and template (yourgamename.view.php and yourgamename_yourgamename.tpl)]]
==== Other components ====
* [[Game options and preferences (gameoptions.inc.php)]]
[[Studio function reference]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
1072c45c47be8bd6020ce2a38ed8a472b8cc97cf
441
438
2013-01-05T10:14:00Z
Sourisdudesert
1
/* BGA Studio documentation */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic (yourgamename.js)]]
* [[Game art (img directory)]]
* [[Game interface stylesheet (yourgamename.css)]]
* [[Game layout: view and template (yourgamename.view.php and yourgamename_yourgamename.tpl)]]
==== Other components ====
* [[Game options and preferences (gameoptions.inc.php)]]
[[Studio function reference]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
fd2c9b3cfb81e63f498e7363e2a6550c66091a2f
450
441
2013-01-05T10:17:16Z
Sourisdudesert
1
/* BGA Studio documentation */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Game options and preferences: gameoptions.inc.php]]
[[Studio function reference]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
62bbce3b9b3b136dadd05103b019629bcaac908f
Studio FAQ
0
53
410
390
2012-12-09T20:19:37Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the Developer tools with Chrome which has about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the save/restore functionality (NB: currently non functional, will be ok with the next studio update). It enable you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
ef1e7e780ff9d182e7f6232aae6cca4f1616f718
411
410
2012-12-09T20:21:23Z
Een
3
/* What is the best way to debug? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the Developer tools with Chrome which has about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality (NB: currently non functional, will be ok with the next studio update). It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
f65463a81a57517a503e0f7b4adc233b9926ba58
412
411
2012-12-09T20:42:02Z
Een
3
/* What is the best way to debug? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the Developer tools with Chrome which has about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
a244da1f57822595825408622baa1c79d71d759f
413
412
2012-12-09T20:46:36Z
Een
3
/* What is the best way to debug? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
4a1d7d389aee2ef5066258585ecfc2056b52cde0
420
413
2012-12-23T17:17:40Z
Een
3
/* What is the best way to debug? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389: Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
dd8456a862c8ae6069b019e08227068406386654
421
420
2012-12-23T17:18:00Z
Een
3
/* Some frequent errors */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
03c40861e6f13964b3afa0ce1e9f0d483e12882a
The Boss
0
46
415
217
2012-12-15T07:48:27Z
Sweetnaty
1920
/* Description */
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
'''Цель игры.'''
1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом в низ.
2. В конце игры выигрывают игроки которые больше всего заработали миллионов.
'''
Описание'''
В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников.
'''Раунд:'''
1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников.
2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся.
Когда у каждого игрока остается по две карты на руках, открывается карта полиции.
Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками.
''Если вы выигрываете « пистолет», то ваш гангстер убит,
если «решетка» – гангстер не участвует в игре в течение 2-ух раундов,
если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда.
Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.''
'''Карта Чикаго(Алькапоне).'''
У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону.
'''Подсказки новичкам.'''
Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
ec426d7a7f218f82ecde489ba149533dc36b1aa3
416
415
2012-12-15T07:48:54Z
Sweetnaty
1920
/* Goal */
wikitext
text/x-wiki
'''Цель игры.'''
1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом в низ.
2. В конце игры выигрывают игроки которые больше всего заработали миллионов.
'''
Описание'''
В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников.
'''Раунд:'''
1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников.
2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся.
Когда у каждого игрока остается по две карты на руках, открывается карта полиции.
Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками.
''Если вы выигрываете « пистолет», то ваш гангстер убит,
если «решетка» – гангстер не участвует в игре в течение 2-ух раундов,
если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда.
Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.''
'''Карта Чикаго(Алькапоне).'''
У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону.
'''Подсказки новичкам.'''
Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
881a4b4353af0bd885bae8ed8e22b845fd106ad1
417
416
2012-12-15T07:49:42Z
Sweetnaty
1920
/* Beginner Tips */
wikitext
text/x-wiki
'''Цель игры.'''
1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом в низ.
2. В конце игры выигрывают игроки которые больше всего заработали миллионов.
'''
Описание'''
В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников.
'''Раунд:'''
1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников.
2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся.
Когда у каждого игрока остается по две карты на руках, открывается карта полиции.
Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками.
''Если вы выигрываете « пистолет», то ваш гангстер убит,
если «решетка» – гангстер не участвует в игре в течение 2-ух раундов,
если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда.
Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.''
'''Карта Чикаго(Алькапоне).'''
У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону.
'''Подсказки новичкам.'''
Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион.
b47bbe214e6ce4ab1cc0aa683a747d92216769da
418
417
2012-12-15T18:40:21Z
Sweetnaty
1920
wikitext
text/x-wiki
'''Цель игры.'''
1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом вниз).
2. В конце игры выигрывают игроки которые больше всего заработали миллионов.
'''
Описание'''
В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников.
'''Раунд:'''
1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников.
2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся.
Когда у каждого игрока остается по две карты на руках, открывается карта полиции.
Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками.
''Если вы выигрываете « пистолет», то ваш гангстер убит,
если «решетка» – гангстер не участвует в игре в течение 2-ух раундов,
если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда.
Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.''
'''Карта Чикаго(Алькапоне).'''
У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону.
'''Подсказки новичкам.'''
Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион.
45d5f6a85beada1c1bf36cf6ec5b930d4354e8f2
419
418
2012-12-15T18:41:21Z
Sweetnaty
1920
wikitext
text/x-wiki
'''Цель игры.'''
1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом вниз).
2. В конце игры выигрывают игроки которые больше всего заработали миллионов.
'''
Описание''''''
'''
В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников.
'''Раунд:'''
1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников.
2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся.
Когда у каждого игрока остается по две карты на руках, открывается карта полиции.
Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками.
''Если вы выигрываете « пистолет», то ваш гангстер убит,
если «решетка» – гангстер не участвует в игре в течение 2-ух раундов,
если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда.
Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.''
'''Карта Чикаго(Алькапоне).'''
У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону.
'''Подсказки новичкам.'''
Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион.
fda07a0572c0515408272f1bd3015ebe97a36b9f
423
419
2012-12-30T18:59:04Z
Spacediver
718
reverted English back, moved Russian into corresponding separate page.
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
216df9ddb16c37d4791196cf9503d42bd9c7b533
Gamehelpgomoku
0
81
422
2012-12-24T12:55:06Z
Een
3
Created page with " == Goal == Create an unbroken row of exactly five stones of your color horizontally, vertically, or diagonally. Overlines (rows of 6 stones or more) do not count. == Vari..."
wikitext
text/x-wiki
== Goal ==
Create an unbroken row of exactly five stones of your color horizontally, vertically, or diagonally.
Overlines (rows of 6 stones or more) do not count.
== Variant ==
In Gomoku+ (also named Caro) in order to win your row of five stones must be free at both ends.
This balances the game differently and gives more defensive power to the white player.
== Openings ==
Black always play first.
With the 'standard' (free) opening, black has got a distinct advantage over white who is directly put 'under attack'.
The 'tournament' opening aims to even the odds between the black and white players:
* black lays the first stone at the center of the board
* white lays the second stone in one of the spaces adjoining to the center of the board (horizontally, vertically or diagonally)
* black lays the third stone at least three spaces away from the center of the board.
7a98f64e6b90bd76c2333efa14892ecb86a538ec
사용자토론:Sweetnaty
3
82
424
2012-12-30T19:01:39Z
Spacediver
718
Перевод описания игры ;)
wikitext
text/x-wiki
== Перевод описания игры ;) ==
Русский перевод описания игры нужно делать не поверх английского, который открывается отсюда:
http://en.boardgamearena.com/#!gamepanel?game=theboss
...а на отдельной странице русского описания, куда ведет ссылка с '''русской версии''' сайта (обрати внимание на URL)
http://ru.boardgamearena.com/#!gamepanel?game=theboss
ca8e0ebb2778d155cb96b4f1de657321806eb7db
Gamehelphawaii
0
34
425
101
2013-01-01T20:20:23Z
Tobylongbeach
477
wikitext
text/x-wiki
Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. There are five rounds and you get a decreasing amount of resources each round with which to acquire place tiles. Its a many-paths-to-victory kind of game. (It has been described as Stone Age without the dice).
There are three kinds of resources:
1) Feet - let you move around the board, or travel to the islands or go to the cove to catch fish.
2) Clam shells - let you buy place tiles from the board
3) Fruit - can be used in place of feet or clam shells in all-or-nothing fashion. If you substitute for feet, you must substitute the entire moving cost. If you substitute for clams, you must substitute the entire purchase price.
Moving: Your chieftains start at the beach and it costs nothing to return there from the board. Each movement in from the beach costs one foot. Moving up, down, right, left or diagonal on the board costs one foot per space. Staying on a space costs one foot.
To go to the islands, you use your boats and feet. The closest island costs three feet and the farthest costs six. You have to have the feet as well as the space on the boats for the feet. You get an immediate victory point bonus for going to the islands but you do not get a price token (more about that later). Also, you get the level 2 version of whatever place tile or item you are getting on the islands.
For instance, to go to the six foot island, you would need either:
A) two three-feet boats and six feet resources or
B) you would need the four-foot boat (which comes with a prepaid foot) and the two-foot boat as well as five feet resources. That is the advantage of the pre-paid foot on the four-foot boat.
== Purchasing: ==
To buy some thing from the board: Select the price token (round colored circle with number inside) on the space with the place tile or item you want. If there is more than one place tile available on that space, you will be given a choice of which one you want. The movement cost will be in feet and the purchase price will be in clam shells but you can substitute either or both with fruit if you have it. You gain the price token for the round. There must be an available price token in order to purchase something from that space.
You can pay double to get the level 2 version, which for most tiles is double effect.
You place it in the village (row) of your choice. You must be able to place it in order to purchase it.
A) You can only have one of each type of place tile in each village. For instance, you cannot have a foot (1) hut and a foot (2) hut in the same village but you can have a coconut fruit (1) tree and a breadfruit (2) tree in the same village.
B) You can have only one god in each village. You can only have one of each type of god in your whole kingdom and the god vp effects are kingdom-wide.
B) Each village must begin with a hut. The huts have a picture of a hut on them: foot hut, clam hut, spear hut, exchange hut, and long hut.
'''
== Resources ==
'''
== Base reources ==
Base resources are on the round indicator. They decrease with each succeeding round. Everyone gets the base resources at the beginning of the round. Any unused resources can be used in the next round.
== In-play resource bonuses ==
*The third, fourth and fifth villages give you 1, 2 and 3 clams respectively when you purchase Kahunas (Hawaiian priests) for them.
*When you purchase for your kingdom the second, third and fourth Tikis, you are granted 1, 2, and 3 feet, respectively.
*One or two of the island treasures are four fruit resources.
== Resource Generators: == generate resources at the beginning of the next round.
*Fruit level ones - one fruit
*Fruit level twos - two fruit
*Clam hut level one - one clam
*Clam hut level two - two clams
*Foot hut level one - one foot
*Foot hut level two - two feet
*Irrigation level two - one resource of your choice
*Ku god - level one and two - one foot
*Kane god level one - one clam
*Kane god level two - two clams
== Converter huts ==
Whenever you spend resources, a level 1 converter hut allows you to substitute one resource of your choice. So, for instance, you could move one space and buy something that has four price token on it with four fruit for the token and one clamshell being substituted for the one foot movement. Another example, you could go to the first island for two feet and one clamshell using a level 1 boat. The converter level 2 hut is the same but with any two resources.
'''== Victory Points =='''
== In-play VP's: ==
*Going to the islands gives you a vp bonus.
*Some of the treasures on the islands are 5 vp's.
*Spear huts and the Ku god give you a bonus whenever you take a price token with crossed spears. Level 1 is 1 pt. bonus, Level 2 is two pt. bonus.
== Round-End VP's: ==
There is a large sheild on the round indicator at the bottom. If the sum of price tokens and fish are greater than the number on the sheild, then you get a bonus. There is a large bonus for the player with highest sum score, a moderate bonus for the second highest and a token bonus for everyone else whose sum was greater than the sheild. Surfer place tiles lower the sheild value for qualifying for the bonus but surfers do not contribute to your sum when comparing to other players.
Lono god level 1 gives you 2 vp's if you qualify for the bonus, and Lono god level 2 gives you 4 vp's if you qualify for the bonus
== Game-End VP's: ==
A) Each village whose size does not extend to the Tikis is ignored for end-game scoring - its place tiles do not count and neither does its Kahuna. The villages below it are not affected - each village must reach the Kahunas independently.
B) The Kahunas on the first, second, third, fourth and fifth villages scores the player five, five, ten, ten and fifteen points respectively.
B) A hula dancer in a village scores one point for each place tile in her village including herself. A level 2 hula dancer scores two points instead of one for each place tile in her village including herself.
C) Irrigation gives you pts for each type of fruit you have in that particular village: Breadfruit, guava, coconuts and bananas.
D) The Long Hut level 2 is worth five points. The long hut level one just takes up space making it easier to reach the Kahunas but does not, itself, score points.
E) The Laka god in your kingdom scores one pt for each fruit symbol on your place tiles in all of the villages which is the whole kingdom. Laka god level 2 scores two points for each fruit symbol.
F) Kanaloa god scores two pts for each boat and each surfer on all the villages in the kingdom. Kanaloa 2 scores 4 pts for each boat and surfer.
5948df612fd3dc390051357ccb7e029823e4562b
Browser support
0
13
426
69
2013-01-03T16:00:30Z
Een
3
wikitext
text/x-wiki
[[Category:Help]]
<h3>For the best experience, we recommend:</h3>
* '''Google Chrome 10+''' [http://www.google.com/chrome Windows] [http://www.google.com/chrome?platform=mac Mac] [http://www.google.com/chrome?platform=linux Linux]
* '''Mozilla Firefox 4+''' [http://www.mozilla.org/products/firefox/ Windows] [http://www.mozilla.org/products/firefox/ Mac] [http://www.mozilla.org/products/firefox/ Linux]
Board Game Arena takes advantage of the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download or update, no plugins to install, etc.
Consequently, to play you need to use a modern web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be.
This website makes intensive use of Javascript and your browser's graphics capabilities. Thus, if you want to have the best gaming experience with Board Game Arena, you should use one of the browsers listed above. However, we officially support the following browsers:
* Google Chrome 4+
* Mozilla Firefox 3.5+
* Internet Explorer 9+
* Safari 4+
(Note: We do NOT support playing on iPads or similar tablets.)
82c74a446ab46ee91347f67d008b263af608ce10
Help
0
4
427
219
2013-01-05T09:30:25Z
Sourisdudesert
1
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena]]
** [[About us]]
** [[Club Board Game Arena]]
** [[Contact us]]
=== Detailed help ===
* [[Getting started]]
* [[Referral]]
* [[Browser support]]
* [[Moderation and grades]]
* [[Game clock]]
* [[Rating]]
* [[Reputation]]
* [[Translation guidelines]]
c6067b5fc3f21568031e1b54885fd097134d4f1d
How to join BGA developer team?
0
83
431
2013-01-05T09:46:40Z
Sourisdudesert
1
Created page with " Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to b..."
wikitext
text/x-wiki
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your player user name on BGA
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
<pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly,
we will work only with 3 fearless developers on 3 simple games.</pre>
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
e2db83f30a3fec64e81365b9198379fb7aaf63b7
Studio file reference
0
54
439
319
2013-01-05T10:11:33Z
Sourisdudesert
1
/* states.inc.php */
wikitext
text/x-wiki
This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment.
=== 'img' directory ===
This directory contains the images for your game:
* game_box.png is displayed on the main site on the game description page and when creating a table (280x280 px)
* game_icon.png is the icon displayed in the lists of games and tables (50x50 px)
* publisher.png is the logo of the publisher of the game, displayed on the game description page (width: 150 px)
* and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance.
=== dbmodel.sql ===
File for creating specific database tables that you will need to persist data during the game (for example a table for cards).
=== gameoptions.inc.php ===
File for describing your game options (= game variants)
=== <gamename>.action.php ===
File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions.
=== <gamename>.css ===
CSS styles specific to your game.
=== <gamename>.game.php ===
This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
=== <gamename>.js ===
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
=== <gamename>.view.php and <gamename>_<gamename>.tpl ===
Files used to set up the page layout ('view') for the game.
=== material.inc.php ===
File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants.
=== states.inc.php ===
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
=== stats.inc.php ===
File used to list statistics that you want to update during the game to be presented to players at the end of the game.
8c614009c3b9805382342cdc1cc704652e8f0897
Players actions (yourgamename.action.php)
0
84
440
2013-01-05T10:12:58Z
Sourisdudesert
1
Created page with "=== APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $defaul..."
wikitext
text/x-wiki
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
b249dbfc2f08f19e51c808b946b0ee96fbb467e6
Players actions: yourgamename.action.php
0
85
442
2013-01-05T10:14:07Z
Sourisdudesert
1
Created page with "=== APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $defaul..."
wikitext
text/x-wiki
=== APP_GameAction class (<gamename>.action.php) ===
; function isArg( $argName )
: Is this argument filled ?
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: Get script argument with the correct type
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
define( 'AT_int', 0 ); // an integer
define( 'AT_posint', 1 ); // a positive integer
define( 'AT_float', 2 ); // a float
define( 'AT_email', 3 ); // an email
define( 'AT_url', 4 ); // a URL
define( 'AT_bool', 5 ); // 1/0/true/false
define( 'AT_enum', 6 ); // argTypeDetails list the possible values
define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space
</pre>
b249dbfc2f08f19e51c808b946b0ee96fbb467e6
Studio function reference
0
55
443
392
2013-01-05T10:14:23Z
Sourisdudesert
1
/* APP_GameAction class (.action.php) */
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below.
== Server side (PHP functions) ==
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
67089d3595e14018b2123d14b1494161851413cb
445
443
2013-01-05T10:14:52Z
Sourisdudesert
1
/* Table class (.game.php) */
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below.
== Server side (PHP functions) ==
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
44a0e60d2e0d37b86e80e3dd236f2f8fbe58c8fd
448
445
2013-01-05T10:16:23Z
Sourisdudesert
1
/* Exceptions you can throw */
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below.
== Server side (PHP functions) ==
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
2a86068880a0d99bb4bbd5114e55f46dc395295c
Main game logic: yourgamename.game.php
0
86
444
2013-01-05T10:14:46Z
Sourisdudesert
1
Created page with "=== Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; functio..."
wikitext
text/x-wiki
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
d6b0fc4adabe456d434028c91896088ba3d49559
446
444
2013-01-05T10:15:22Z
Sourisdudesert
1
wikitext
text/x-wiki
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
cc95d4afc675e2d76a97502cc585135882ee4467
미디어위키:Sidebar
8
2
447
2
2013-01-05T10:16:09Z
Sourisdudesert
1
wikitext
text/x-wiki
* navigation
** http://boardgamearena.com|BoardGameArena.com
** mainpage|mainpage-description
** Studio|BGA Studio doc
** recentchanges-url|recentchanges
* SEARCH
* TOOLBOX
* LANGUAGES
c14629314b9ab77a3a7e98dd4e81d67ff8b7634e
Game interface logic (yourgamename.js)
0
87
449
2013-01-05T10:16:36Z
Sourisdudesert
1
Created page with "== Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the t..."
wikitext
text/x-wiki
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
1e8dc993d4a1c11e472e5365ef1cd2b1e2306264
Game interface logic: yourgamename.js
0
88
451
2013-01-05T10:17:58Z
Sourisdudesert
1
Created page with "; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; thi..."
wikitext
text/x-wiki
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
f579fca77b6768cc083f8382df27a363a405db43
Studio
0
49
452
450
2013-01-05T10:19:35Z
Sourisdudesert
1
/* BGA Studio documentation */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Game options and preferences: gameoptions.inc.php]]
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
2e931b3065efa50525fe88c1fe3cb0780242e182
470
452
2013-01-11T12:06:01Z
Sourisdudesert
1
/* BGA Studio documentation */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Game options and preferences: gameoptions.inc.php]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
c9cc10a2bb0d2ebc0e9a8423b365bf4d2c928557
501
470
2013-01-11T15:47:24Z
Sourisdudesert
1
/* Other components */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
0b06c55548d666ef11e610ff3549d651ed1dafa2
Studio file reference
0
54
453
439
2013-01-05T10:20:18Z
Sourisdudesert
1
/* 'img' directory */
wikitext
text/x-wiki
This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment.
=== 'img' directory ===
This directory contains the images for your game.
=== dbmodel.sql ===
File for creating specific database tables that you will need to persist data during the game (for example a table for cards).
=== gameoptions.inc.php ===
File for describing your game options (= game variants)
=== <gamename>.action.php ===
File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions.
=== <gamename>.css ===
CSS styles specific to your game.
=== <gamename>.game.php ===
This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
=== <gamename>.js ===
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
=== <gamename>.view.php and <gamename>_<gamename>.tpl ===
Files used to set up the page layout ('view') for the game.
=== material.inc.php ===
File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants.
=== states.inc.php ===
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
=== stats.inc.php ===
File used to list statistics that you want to update during the game to be presented to players at the end of the game.
2e7104613bcd7d665c1d222af10c97e42d262d56
454
453
2013-01-05T10:20:49Z
Sourisdudesert
1
/* 'img' directory */
wikitext
text/x-wiki
This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment.
=== 'img' directory ===
This directory contains the images for your game (the game art).
=== dbmodel.sql ===
File for creating specific database tables that you will need to persist data during the game (for example a table for cards).
=== gameoptions.inc.php ===
File for describing your game options (= game variants)
=== <gamename>.action.php ===
File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions.
=== <gamename>.css ===
CSS styles specific to your game.
=== <gamename>.game.php ===
This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
=== <gamename>.js ===
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
=== <gamename>.view.php and <gamename>_<gamename>.tpl ===
Files used to set up the page layout ('view') for the game.
=== material.inc.php ===
File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants.
=== states.inc.php ===
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
=== stats.inc.php ===
File used to list statistics that you want to update during the game to be presented to players at the end of the game.
d8bd4830bfb0b86dcdf637549a560f991d2667ba
Game art: img directory
0
89
455
2013-01-05T10:38:20Z
Sourisdudesert
1
Created page with "== Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (28..."
wikitext
text/x-wiki
== Requested images ==
The following images are requested by BGA:
;game_box.png
* It is displayed on the main site on the game description page and when creating a table (280x280 px).
* It should be an image of a physical copy of the game box as it appears in an online shop.
* It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game.
* The background of the image must be transparent.
;game_icon.png
* It is the icon displayed in the lists of games and tables (50x50 px).
* This one should not be transparent, and shouldn't have a border (a black border will be add by BGA).
* The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title).
;publisher.png
* It is the logo of the publisher of the game, displayed on the game description page.
* The width must be 150 px. The height can be anything. The image could be transparent.
== Game art ==
You must upload in img directory all images of your game interface.
=== Images loading ===
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
Note that you can tune the way images are loaded with Javascript methods "dontPreloadImage" and "ensureSpecificImageLoading" (see [[Game_interface_logic:_yourgamename.js]]).
=== Images format ===
You can use 3 image format while building your game interface:
;jpg images
should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load.
;png images
should be used for transparent images.
;gif images
can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful.
* and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance.
1dc31974112f183a7fcaed36d1d945a3cc155fd2
456
455
2013-01-05T10:38:52Z
Sourisdudesert
1
/* Images loading */
wikitext
text/x-wiki
== Requested images ==
The following images are requested by BGA:
;game_box.png
* It is displayed on the main site on the game description page and when creating a table (280x280 px).
* It should be an image of a physical copy of the game box as it appears in an online shop.
* It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game.
* The background of the image must be transparent.
;game_icon.png
* It is the icon displayed in the lists of games and tables (50x50 px).
* This one should not be transparent, and shouldn't have a border (a black border will be add by BGA).
* The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title).
;publisher.png
* It is the logo of the publisher of the game, displayed on the game description page.
* The width must be 150 px. The height can be anything. The image could be transparent.
== Game art ==
You must upload in img directory all images of your game interface.
=== Images loading ===
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
Note that you can tune the way images are loaded with Javascript methods "dontPreloadImage" and "ensureSpecificImageLoading" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]).
=== Images format ===
You can use 3 image format while building your game interface:
;jpg images
should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load.
;png images
should be used for transparent images.
;gif images
can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful.
* and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance.
a4fe8df99a6159ca229086d9623e012f0d009063
457
456
2013-01-05T10:41:44Z
Sourisdudesert
1
/* Game art */
wikitext
text/x-wiki
== Requested images ==
The following images are requested by BGA:
;game_box.png
* It is displayed on the main site on the game description page and when creating a table (280x280 px).
* It should be an image of a physical copy of the game box as it appears in an online shop.
* It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game.
* The background of the image must be transparent.
;game_icon.png
* It is the icon displayed in the lists of games and tables (50x50 px).
* This one should not be transparent, and shouldn't have a border (a black border will be add by BGA).
* The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title).
;publisher.png
* It is the logo of the publisher of the game, displayed on the game description page.
* The width must be 150 px. The height can be anything. The image could be transparent.
== Game art ==
You must upload in img directory all images of your game interface.
=== Images loading ===
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
Note that you can tune the way images are loaded with Javascript methods "dontPreloadImage" and "ensureSpecificImageLoading" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]).
=== Images format ===
You can use 3 image format while building your game interface:
;jpg images
should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load.
;png images
should be used for transparent images.
;gif images
can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful.
=== Use CSS Sprites ===
To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one.
To learn more on CSS Sprites:
* [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)].
* [[Game interface stylesheet: yourgamename.css]]
0784d5f20fdd5fdc96ac6f303ff161afe79a2d9a
458
457
2013-01-05T10:43:51Z
Sourisdudesert
1
/* Requested images */
wikitext
text/x-wiki
== Requested images ==
The following images are requested by BGA:
;game_box.png
* It is displayed on the main site on the game description page and when creating a table (280x280 px).
* It should be an image of a physical copy of the game box as it appears in an online shop.
* It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game.
* The background of the image must be transparent.
;game_icon.png
* It is the icon displayed in the lists of games and tables (50x50 px).
* This one should not be transparent, and shouldn't have a border (a black border will be add by BGA).
* The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title).
;publisher.png
* It is the logo of the publisher of the game, displayed on the game description page.
* The width must be 150 px. The height can be anything. The image could be transparent.
;publisher2.png (optional)
* If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one).
== Game art ==
You must upload in img directory all images of your game interface.
=== Images loading ===
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
Note that you can tune the way images are loaded with Javascript methods "dontPreloadImage" and "ensureSpecificImageLoading" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]).
=== Images format ===
You can use 3 image format while building your game interface:
;jpg images
should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load.
;png images
should be used for transparent images.
;gif images
can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful.
=== Use CSS Sprites ===
To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one.
To learn more on CSS Sprites:
* [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)].
* [[Game interface stylesheet: yourgamename.css]]
d01797346a998de4ef982255fe6e442d5ac27e44
Main game logic: yourgamename.game.php
0
86
459
446
2013-01-05T10:51:52Z
Sourisdudesert
1
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
; function DbQuery( $sql )
: Executes sql query on the database
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty.
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found
: Raise an exception if more than 1 row is returned
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
2e0422c01375873d889cd852153941009f5dee2c
460
459
2013-01-05T11:06:45Z
Sourisdudesert
1
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; function DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
<pre>
Example 1:
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
Example 2:
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0' ),
1235 => 'myuser1' )
)
</pre>
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
fd806d41060480c3e3ad5ff086652fbc30b52eea
461
460
2013-01-05T11:07:26Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; function DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; function getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; function getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0' ),
1235 => 'myuser1' )
)
</pre>
; protected function getNonEmptyCollectionFromDB( $sql )
: Idem, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
86bb80f233b8a2c1bced9630000c454879ac6000
462
461
2013-01-05T11:10:05Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
e0229a8a72f18d407c46e8f9b0f6ced331099012
463
462
2013-01-05T11:10:28Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
=== Table class (<gamename>.game.php) ===
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
; function getPlayersNumber()
: Returns the number of players playing at the table
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
=== Exceptions you can throw ===
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
755a3c27dc759d73a4c99b8e9b888c680c3350d1
464
463
2013-01-05T11:15:56Z
Sourisdudesert
1
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; function getPlayersNumber()
: Returns the number of players playing at the table
; function getActivePlayerId()
: Get the "active_player", whatever what is the current state type
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated. It is not always the active player.
; function getCurrentPlayerName()
: Get the "current_player" name
; function getCurrentPlayerColor()
: Get the "current_player" color
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
417c04fb7af0bff492989ae695f4f345a37c52e4
465
464
2013-01-05T11:19:55Z
Sourisdudesert
1
/* Accessing player informations */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; function getActivePlayerName()
: Get the "active_player" name
; function getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; function getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; function getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; function isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
b4e9344ba235bca69d92731c2f926fbeb2959325
466
465
2013-01-05T11:23:52Z
Sourisdudesert
1
/* Accessing player informations */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: TODO
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
2d204c8553c8d00246f0efaab8c18e8a447179e5
467
466
2013-01-10T16:57:45Z
Pikiou
1872
/* Accessing player informations */ alternative for getPlayersNumber in setupNewGame
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: TODO
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
013a1ae0c029d6b1be62ea12e8269bbe471a6ccd
468
467
2013-01-11T11:48:42Z
Sourisdudesert
1
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: TODO
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
92a6616477137f9c24f2625d6ca7f4c362b5c522
469
468
2013-01-11T11:51:35Z
Sourisdudesert
1
/* Accessing player informations */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
8319df29226e7701f278f183dfafd66173d508ce
487
469
2013-01-11T14:18:47Z
Sourisdudesert
1
/* Accessing player informations */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active
; function activePrevPlayer()
: Make the previous player active
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
d1370aa7c9c631a4b646a39a8b9a3232b9202c2a
488
487
2013-01-11T14:22:33Z
Sourisdudesert
1
/* Game states and active players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
8ea47e5ee7ae9faad7a436fc0ba0812140c00fb4
491
488
2013-01-11T14:41:59Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
0f0aee686502df2f0e731c6f48979a9e608eb757
498
491
2013-01-11T15:33:44Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; function DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; function DbAffectedRow()
: Return the number of row affected by the last operation
; function escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
f5a3c57d55530f819dccea62b703ca23316dd8af
499
498
2013-01-11T15:42:31Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; function checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
3837cd00d2194d98c93a777e1a61827da5feec9b
500
499
2013-01-11T15:44:56Z
Sourisdudesert
1
/* Game states and active players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
b71dd97bac1bd6a6e4f272c0e71c0c642f6f682c
Your game state machine: states.inc.php
0
90
471
2013-01-11T13:19:50Z
Sourisdudesert
1
Created page with " This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the..."
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== Game state ID ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
64db0b4c31e2f6372cd2819e12291f99087f1d58
472
471
2013-01-11T13:24:31Z
Sourisdudesert
1
/* Syntax */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== Game state ID ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
=== Game state name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
122046b59cce388a4eb0e91e6b1ee6ef5669b9f9
473
472
2013-01-11T13:24:58Z
Sourisdudesert
1
/* Game state name */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== Game state ID ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
=== Game state name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
2807b405f3ea0817378ad5eea0e0e6019aff05dc
474
473
2013-01-11T13:39:01Z
Sourisdudesert
1
/* Syntax */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
== description ==
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
== descriptionmyturn ==
984ab22f16888cc5be11c4feefebe2f1cb87832f
475
474
2013-01-11T13:43:11Z
Sourisdudesert
1
/* descriptionmyturn */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
== description ==
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
== descriptionmyturn ==
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
c71d493e9411d9543bfdc4e12064b01331340977
476
475
2013-01-11T13:43:42Z
Sourisdudesert
1
/* description */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
== descriptionmyturn ==
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
90f150994f2c80467670000ba070796d005fc402
477
476
2013-01-11T13:43:48Z
Sourisdudesert
1
/* descriptionmyturn */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
9be143bed66f07c9026f63c1d288e56f45502de9
478
477
2013-01-11T13:45:32Z
Sourisdudesert
1
/* Syntax */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
8a60a37723221c9a982b73cb792a1a9ed9a8eabd
479
478
2013-01-11T13:51:07Z
Sourisdudesert
1
/* descriptionmyturn */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
e53759ccf506d389b182eb85ab80aa719bc7599c
480
479
2013-01-11T13:52:11Z
Sourisdudesert
1
/* id */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
0f7c457ab6a3eacff262fd685514839a3fa65e8b
481
480
2013-01-11T13:52:19Z
Sourisdudesert
1
/* id */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
c42e3bcd700318400aafdc3b1e13b1afe4bdd309
482
481
2013-01-11T14:02:57Z
Sourisdudesert
1
/* action */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
6350bda2becff3188000260128af9be79098886d
483
482
2013-01-11T14:07:59Z
Sourisdudesert
1
/* transitions */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) )
{ return ; }
....
</pre>
a60bd8c9f68bcf0ec45770c0f3a5b39cf652b9f0
484
483
2013-01-11T14:08:14Z
Sourisdudesert
1
/* possibleactions */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
a54b5a8b71b94de9489c426b6e3e7f8d8c17399b
485
484
2013-01-11T14:13:58Z
Sourisdudesert
1
/* possibleactions */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "placeWorkers",
"description" => clienttranslate('${actplayer} must place some workers'),
"descriptionmyturn" => clienttranslate('${you} must place some workers'),
"type" => "activeplayer",
'''"args" => "argPlaceWorkers",'''
"possibleactions" => array( "placeWorkers" ),
"transitions" => array( "nextPlayer" => 11, "nextPhase" => 12, "zombiePass" => 11 )
),
</pre>
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
ab7a9a311b70804a2341683b23ee13310f5b188f
486
485
2013-01-11T14:16:16Z
Sourisdudesert
1
/* args */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"arg" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "placeWorkers",
"description" => clienttranslate('${actplayer} must place some workers'),
"descriptionmyturn" => clienttranslate('${you} must place some workers'),
"type" => "activeplayer",
"args" => "argPlaceWorkers", <================================== HERE
"possibleactions" => array( "placeWorkers" ),
"transitions" => array( "nextPlayer" => 11, "nextPhase" => 12, "zombiePass" => 11 )
),
</pre>
It corresponds to a « argPlaceWorkers » method in our PHP code (reversi.game.php):
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves()
);
}
</pre>
Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn :
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above).
Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn).
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
1cbe5d759b0e2ab2ccc6de088662afa6e71c75b6
Game database model: dbmodel.sql
0
92
490
2013-01-11T14:41:22Z
Sourisdudesert
1
Created page with "In this file you specify the database schema of your game. This file contains SQL queries that will be executed during the creation of your game table. Note: you can't chang..."
wikitext
text/x-wiki
In this file you specify the database schema of your game.
This file contains SQL queries that will be executed during the creation of your game table.
Note: you can't change the database schema during the game.
== Create your schema ==
To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file.
== Default tables ==
Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player.
You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code).
You may add columns to "player" table. This is very practical to add simple values associated with players.
Example:
<pre>
ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7';
</pre>
For your information, the useful columns of default "player" table are:
* player_no: the index of player in natural playing order.
* player_id
* player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods)
* player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores.
* player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game.
2a8820a0ff219470e0d437ff49a161ce7e12ae0f
Players actions: yourgamename.action.php
0
85
492
442
2013-01-11T14:56:04Z
Sourisdudesert
1
wikitext
text/x-wiki
== Purpose of this file ==
With this file, you define all the players entry points (ie: possible game actions) of your game.
This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php".
The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file).
Methods in this file must be short: no game logic must be introduced here.
== Example of typical action method ==
(from Reversi example)
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
== Methods to use in action methods ==
; function setAjaxMode
: Must be use at the beginning of each action method.
; function ajaxResponse
: Must be use at the end of each action method.
; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )
: This method must be used to retrieve the arguments sent with your AJAX query.
: You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe.
: This method use the following arguments:
: * argName: the name of the argument to retrieve.
: * argType: the type of the argument. You should use one of the following:
: 'AT_int' for an integer
: 'AT_posint' for a positive integer
: 'AT_float' for a float
: 'AT_bool' for 1/0/true/false
: 'AT_enum' for an enumeration (argTypeDetails list the possible values as an array)
: 'AT_alphanum' for a string with 0-9a-zA-Z_ and space
: bCanFail means than a validation failure is possible (user input)
: The main argType values are as follows.
<pre>
; function isArg( $argName )
: Return "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not.
</pre>
8c4f55762d427d4ec9ec448bb25c0a942246d00f
493
492
2013-01-11T14:58:20Z
Sourisdudesert
1
/* Methods to use in action methods */
wikitext
text/x-wiki
== Purpose of this file ==
With this file, you define all the players entry points (ie: possible game actions) of your game.
This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php".
The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file).
Methods in this file must be short: no game logic must be introduced here.
== Example of typical action method ==
(from Reversi example)
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
== Methods to use in action methods ==
'''function setAjaxMode'''
Must be use at the beginning of each action method.
'''function ajaxResponse'''
Must be use at the end of each action method.
'''function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )'''
This method must be used to retrieve the arguments sent with your AJAX query.
You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe.
This method use the following arguments:
* argName: the name of the argument to retrieve.
* argType: the type of the argument. You should use one of the following:
'AT_int' for an integer
'AT_posint' for a positive integer
'AT_float' for a float
'AT_bool' for 1/0/true/false
'AT_enum' for an enumeration (argTypeDetails list the possible values as an array)
'AT_alphanum' for a string with 0-9a-zA-Z_ and space
'AT_numberlist' for a list of several numbers separated with "," or ";" (ex: exemple: 1,4;2,3;-1,2).
bCanFail means than a validation failure is possible (user input)
The main argType values are as follows.
'''function isArg( $argName )'''
Return "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not.
</pre>
a19d6dfedf8fe2277f7069fe3b0a5a9c9a7646dd
494
493
2013-01-11T15:03:50Z
Sourisdudesert
1
/* Methods to use in action methods */
wikitext
text/x-wiki
== Purpose of this file ==
With this file, you define all the players entry points (ie: possible game actions) of your game.
This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php".
The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file).
Methods in this file must be short: no game logic must be introduced here.
== Example of typical action method ==
(from Reversi example)
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
== Methods to use in action methods ==
'''function setAjaxMode'''
Must be use at the beginning of each action method.
'''function ajaxResponse'''
Must be use at the end of each action method.
'''function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )'''
This method must be used to retrieve the arguments sent with your AJAX query.
You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe.
This method use the following arguments:
* argName: the name of the argument to retrieve.
* argType: the type of the argument. You should use one of the following:
'AT_int' for an integer
'AT_posint' for a positive integer
'AT_float' for a float
'AT_bool' for 1/0/true/false
'AT_enum' for an enumeration (argTypeDetails list the possible values as an array)
'AT_alphanum' for a string with 0-9a-zA-Z_ and space
'AT_numberlist' for a list of several numbers separated with "," or ";" (ex: exemple: 1,4;2,3;-1,2).
* mandatory: specify "true" if the argument is mandatory.
* default: if mandatory=false, you can specify here a default value in case the argument is not present.
* argTypeDetails: see AT_enum above.
* bCanFail: if true, specify that it may be possible that the argument won't be of the type specified by argType (and then do not log this as a fatal error in the system, and return a standard exception to the player).
'''function isArg( $argName )'''
This is a useful method when you only want to check if an argument is present or not present in your AJAX request (and don't care of the value.
It returns "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not.
46067eef7c4401ee68e1c3a4512ab090091e4c1d
495
494
2013-01-11T15:07:01Z
Sourisdudesert
1
/* Methods to use in action methods */
wikitext
text/x-wiki
== Purpose of this file ==
With this file, you define all the players entry points (ie: possible game actions) of your game.
This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php".
The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file).
Methods in this file must be short: no game logic must be introduced here.
== Example of typical action method ==
(from Reversi example)
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
== Methods to use in action methods ==
'''function setAjaxMode'''
Must be use at the beginning of each action method.
'''function ajaxResponse'''
Must be use at the end of each action method.
'''function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )'''
This method must be used to retrieve the arguments sent with your AJAX query.
You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe.
This method use the following arguments:
* argName: the name of the argument to retrieve.
* argType: the type of the argument. You should use one of the following:
'AT_int' for an integer
'AT_posint' for a positive integer
'AT_float' for a float
'AT_bool' for 1/0/true/false
'AT_enum' for an enumeration (argTypeDetails list the possible values as an array)
'AT_alphanum' for a string with 0-9a-zA-Z_ and space
'AT_numberlist' for a list of several numbers separated with "," or ";" (ex: exemple: 1,4;2,3;-1,2).
* mandatory: specify "true" if the argument is mandatory.
* default: if mandatory=false, you can specify here a default value in case the argument is not present.
* argTypeDetails: see AT_enum above.
* bCanFail: if true, specify that it may be possible that the argument won't be of the type specified by argType (and then do not log this as a fatal error in the system, and return a standard exception to the player).
'''function isArg( $argName )'''
This is a useful method when you only want to check if an argument is present or not present in your AJAX request (and don't care of the value.
It returns "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not.
== Useful tip: retrieve a list of number ==
If your Javascript send a list of integer separated by ";" (ex: "1;2;3;4") as an argument, you can transform them in a PHP array with the following:
<pre>
public function playCards()
{
self::setAjaxMode();
$card_ids_raw = self::getArg( "card_ids", AT_numberlist, true );
// Removing last ';' if exists
if( substr( $card_ids_raw, -1 ) == ';' )
$card_ids_raw = substr( $card_ids_raw, 0, -1 );
if( $card_ids_raw == '' )
$card_ids = array();
else
$card_ids = explode( ';', $card_ids_raw );
$this->game->playCards( $card_ids );
self::ajaxResponse( );
}
</pre>
bae1cc6ec52c6feadc80d3bd3e4aa03ff95908b8
Game material description: material.inc.php
0
93
496
2013-01-11T15:18:46Z
Sourisdudesert
1
Created page with "This PHP file describes all the material of your game. This file is include by the constructor of your main game logic (yourgame.game.php), and then the variables defined her..."
wikitext
text/x-wiki
This PHP file describes all the material of your game.
This file is include by the constructor of your main game logic (yourgame.game.php), and then the variables defined here are accessible everywhere in your game logic file.
Example from "Hearts": if you define this in material.inc.php:
<pre>
$this->colors = array(
1 => array( 'name' => clienttranslate('spade'),
'nametr' => self::_('spade') ),
2 => array( 'name' => clienttranslate('heart'),
'nametr' => self::_('heart') ),
3 => array( 'name' => clienttranslate('club'),
'nametr' => self::_('club') ),
4 => array( 'name' => clienttranslate('diamond'),
'nametr' => self::_('diamond') )
);
</pre>
... you can access "$this->colors" everywhere in your PHP game logic file.
076a3890e55f1fa9e5466f29cde040c46ffe67c0
497
496
2013-01-11T15:23:52Z
Sourisdudesert
1
wikitext
text/x-wiki
This PHP file describes all the material of your game.
This file is include by the constructor of your main game logic (yourgame.game.php), and then the variables defined here are accessible everywhere in your game logic file.
Using material.inc.php makes your PHP logic file smaller and clean.
Example from "Hearts": if you define this in material.inc.php:
<pre>
$this->colors = array(
1 => array( 'name' => clienttranslate('spade'),
'nametr' => self::_('spade') ),
2 => array( 'name' => clienttranslate('heart'),
'nametr' => self::_('heart') ),
3 => array( 'name' => clienttranslate('club'),
'nametr' => self::_('club') ),
4 => array( 'name' => clienttranslate('diamond'),
'nametr' => self::_('diamond') )
);
</pre>
... you can access "$this->colors" everywhere in your PHP game logic file.
e7a93d7e58d52c2a8bef0f954da5a495b33020f5
Translations
0
94
502
2013-01-11T15:47:33Z
Sourisdudesert
1
Created page with " (todo)"
wikitext
text/x-wiki
(todo)
5d301b12a9331eb33c9c5d7c0fa41fb6c5d4ba56
503
502
2013-01-11T15:47:46Z
Sourisdudesert
1
wikitext
text/x-wiki
; function _( $text )
: Transparent function, used to mark strings to be translated on the server side (ex: error message)
; function clienttranslate( $string )
: Transparent function: used to mark string to be translated on client side (ex: notification message)
24c00b9c260eebd9acf6ee6ac66fb2fb049781c3
530
503
2013-01-15T16:55:04Z
Sourisdudesert
1
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
7faacf163abbdcae5aa87a9f68ef1964d1c12b63
531
530
2013-01-15T16:57:24Z
Sourisdudesert
1
/* On server side (PHP) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
aef6fc156d64ae4fb1e6e7bcdc3e4b83b5165666
532
531
2013-01-15T17:03:59Z
Sourisdudesert
1
/* On server side (PHP) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
519d1b8d8f83dc3f8ef485ff25657a06063da52e
533
532
2013-01-15T17:04:47Z
Sourisdudesert
1
/* On server side (PHP) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
9315062d846ea128dd8a5731f15b03d70346e96e
534
533
2013-01-15T17:07:34Z
Sourisdudesert
1
/* On server side (PHP) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
b0251a213ab68551932ef7c5129f4d59dce827af
Main game logic: yourgamename.game.php
0
86
504
500
2013-01-11T15:47:57Z
Sourisdudesert
1
/* Translations */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
852a46f013f70307a38382fd2ee5c3d0d18c797e
505
504
2013-01-11T15:49:19Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Using globals ==
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
8d73b6994cd02253b43a940b0d520f77233a8f8c
506
505
2013-01-11T15:58:07Z
Sourisdudesert
1
/* Using globals */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
636e63e3bc63774d2554983bed02eb9b115cf506
508
506
2013-01-11T16:03:04Z
Sourisdudesert
1
/* Game states and active players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Players turn order ==
'''createNextPlayerTable( $players, $bLoop=true )'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
$players = self::loadPlayersBasicInfos()
$nextPlayers = createNextPlayerTable( $players ); // return array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 );
$nextPlayers = createNextPlayerTable( $players, false ); // return array( 1 => 2, 2 => 3, 0 => 1 );
</pre>
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
1d8d43d07f3ec3d264df38a6db890b7754487155
509
508
2013-01-11T16:06:05Z
Sourisdudesert
1
/* Players turn order */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
5cda35c29ef2339660b1b9ef0cac8c40f36762c1
510
509
2013-01-11T16:06:52Z
Sourisdudesert
1
/* Players turn order */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player (standard extra time is a game option)
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
08c40fe97a1b285f7b648813931d0f4fed42c8d4
511
510
2013-01-11T16:08:42Z
Sourisdudesert
1
/* Reflexion time */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
== Game statistics ==
; function initStat( $table_or_player, $name, $value, $player_id=null )
: Create a statistic entry for the specified statistics with a default value
: In case of a "player" entry, if player_id is not specified, all players are set to the same value
; function setStat( $value, $name, $player_id = null )
: Set statistic value
; function incStat( $delta, $name, $player_id = null )
: Increment (or decrement) specified value
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
b916b96471dd091a82c47c1a595813f6813fe122
513
511
2013-01-11T16:15:56Z
Sourisdudesert
1
/* Game statistics */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
30e4fbe4a7a9f3484375ac3e49c4de8ffb430c28
514
513
2013-01-11T16:24:11Z
Sourisdudesert
1
/* Notify players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
c736610fc329a786629ddf77ed3612ca3a6e0400
515
514
2013-01-11T16:26:41Z
Sourisdudesert
1
/* Notify players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; function activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; function activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
64e2d717a68cd4e452a230b8dd290fc7c24a1779
516
515
2013-01-11T16:29:48Z
Sourisdudesert
1
/* Game states and active players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
0c9f99bbd1eec9cc35913e05464c1cab169d9918
517
516
2013-01-11T16:38:09Z
Sourisdudesert
1
/* Game states and active players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
; throw new BgaSystemVisibleException ( $error_message)
: Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user.
3602613dae96f6572bb8b2b05719baaf61a71a93
518
517
2013-01-11T16:45:57Z
Sourisdudesert
1
/* Managing errors and exceptions */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
7669befb882381077e8b9eead19707ff5f3d32b6
Help
0
4
507
427
2013-01-11T16:02:09Z
Een
3
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena|About Board Game Arena]]
** [[About us|About us]]
** [[Club Board Game Arena|Club Board Game Arena]]
** [[Contact us|Contact us]]
=== Detailed help ===
* [[Getting started|Getting started]]
* [[Referral|Referral]]
* [[Browser support|Browser support]]
* [[Moderation and grades|Moderation and grades]]
* [[Game clock|Game clock]]
* [[Rating|Rating]]
* [[Reputation|Reputation]]
* [[Translation guidelines|Translation guidelines]]
401acc1457522cd40f7eeb302f5488ea375cbacb
Game statistics: stats.inc.php
0
95
512
2013-01-11T16:11:38Z
Sourisdudesert
1
Created page with " (todo)"
wikitext
text/x-wiki
(todo)
144a80e923365406965058d618e72ad9edcf31e0
519
512
2013-01-11T16:52:46Z
Sourisdudesert
1
wikitext
text/x-wiki
(to be completed)
=> see comments in your stats.inc.php file
a01448ec26bcc5d5e1468c200ce2385a6c5e3145
Game interface stylesheet: yourgamename.css
0
96
520
2013-01-11T17:05:10Z
Sourisdudesert
1
Created page with "This is the CSS stylesheet of your game User Interface. Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourga..."
wikitext
text/x-wiki
This is the CSS stylesheet of your game User Interface.
Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript.
Usually, you are using CSS to:
1°) define the overall layout of your game
(ex: place the board on the top left, place player's hand beside, place the deck on the right, ...).
2°) create your CSS-sprites:
All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly.
Example:
<pre>
Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image):
.white_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: 0px 0px;
}
.black_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: -20px 0px;
}
.token {
width: 20px;
height: 20px;
background-repeat: none;
}
</pre>
3°) ... anything else:
It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query).
This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily.
Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary.
e3a85e1f26e247f89f549b3427b62770dd4ba20f
How to join BGA developer team?
0
83
521
431
2013-01-13T12:07:41Z
Een
3
/* Ok, I registered, what do I get? */
wikitext
text/x-wiki
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your player user name on BGA
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, we'll discuss by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
93291e486ca904e0dbed17dcadb4a04271acd827
Game interface logic: yourgamename.js
0
88
522
451
2013-01-14T16:02:38Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
TODO
== Useful methods from the BGA framework ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
2d591248b137f4f336137161c6c0d8e6fadc5784
523
522
2013-01-14T16:22:11Z
Sourisdudesert
1
/* Dojo framework */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Useful methods from the BGA framework ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
f958116cefb92037d99b5803494b0e77dc5933bb
524
523
2013-01-14T16:28:08Z
Sourisdudesert
1
/* Dojo framework */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''dojo.style'''
TODO
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Useful methods from the BGA framework ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
dfcc464befa61dd55fbf2d1dbfbbedc4f8e8ad8c
525
524
2013-01-14T16:46:51Z
Sourisdudesert
1
/* Dojo framework */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Useful methods from the BGA framework ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
e4a4a9ede4662eeb6aba9c6aeacf08c55cfd91d0
526
525
2013-01-14T17:21:17Z
Sourisdudesert
1
/* Dojo framework */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
== Useful methods from the BGA framework ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
07e0e96af372326eb1ccde8fd9b13758b8e25c31
527
526
2013-01-14T17:23:33Z
Sourisdudesert
1
/* Dojo framework */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
'''dojo animations'''
See "animations" below.
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
== Useful methods from the BGA framework ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
df3c2d0d3f9af0259ea4c3a8c70edf7422cad672
528
527
2013-01-14T17:27:28Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
== Access and manipulate the DOM ==
== Animations ==
== Players input ==
(dojo.connect/checkAction/ajaxcall/confirmationDialog)
== Notifications ==
== Tooltips ==
== BGA GUI components ==
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
'''dojo animations'''
See "animations" below.
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
== Useful methods from the BGA framework ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
808f170e17bf773369f5fa182d57e47ad36472f3
535
528
2013-01-15T17:28:55Z
Sourisdudesert
1
/* Useful methods from the BGA framework */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
== Access and manipulate the DOM ==
== Animations ==
== Players input ==
(dojo.connect/checkAction/ajaxcall/confirmationDialog)
== Notifications ==
== Tooltips ==
== BGA GUI components ==
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
'''dojo animations'''
See "animations" below.
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
== Useful methods from the BGA framework ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
5a821d5a7574d0e44e801b374da78484bf054ee8
536
535
2013-01-15T17:30:17Z
Sourisdudesert
1
/* General tips */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Access and manipulate the DOM ==
== Animations ==
== Players input ==
(dojo.connect/checkAction/ajaxcall/confirmationDialog)
== Notifications ==
== Tooltips ==
== BGA GUI components ==
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface:
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
'''dojo animations'''
See "animations" below.
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
== Useful methods from the BGA framework ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
500ffcf842c54b3d538b5b5bf0b09e97d468de80
537
536
2013-01-15T17:39:45Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
TODO
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
== BGA GUI components ==
'''dojo animations'''
See "animations" below.
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
== Useful methods from the BGA framework ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
5925d7515da319684b74df69c34f3c44b7701ac4
538
537
2013-01-15T17:40:11Z
Sourisdudesert
1
/* Useful methods from the BGA framework */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
TODO
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
== BGA GUI components ==
'''dojo animations'''
See "animations" below.
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
== Useful methods from the BGA framework ==
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
75121e76f663a1539f180b725447d90adeecd4d5
539
538
2013-01-15T17:40:21Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
TODO
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
== BGA GUI components ==
'''dojo animations'''
See "animations" below.
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
== Useful methods from the BGA framework ==
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
50f6adb55d71b5fce9f62374c9ab7d9d4861f745
540
539
2013-01-15T17:40:39Z
Sourisdudesert
1
/* BGA GUI components */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
TODO
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
== BGA GUI components ==
== Useful methods from the BGA framework ==
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
90a053e179d91c2b7422976bf185e9f9717fdf62
541
540
2013-01-15T17:41:24Z
Sourisdudesert
1
/* Useful methods from the BGA framework */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
TODO
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
== BGA GUI components ==
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
b8f913e1bc2aa33d972f84996dd998cd11cd3cf2
542
541
2013-01-15T17:41:32Z
Sourisdudesert
1
/* Tooltips */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
TODO
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
e9c7a0524cff660e9ecc2cec157ee42827a9d76e
543
542
2013-01-15T17:41:53Z
Sourisdudesert
1
/* Other useful stuff */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
TODO
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
21cd7cce3f7b0eebdab0b1b4bc17374c27817254
544
543
2013-01-15T17:42:27Z
Sourisdudesert
1
/* Players input */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account: _ current game state & _ interface locking
return true if action is authorized
return false and display an error message if not (display no message if nomessage parameter is true)
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
9c7028944c23584ab2d72a72d9594fd21bb286e0
545
544
2013-01-15T17:44:47Z
Sourisdudesert
1
/* BGA GUI components */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account: _ current game state & _ interface locking
return true if action is authorized
return false and display an error message if not (display no message if nomessage parameter is true)
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface.
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
25369aba21f0c435dfa537d7ac4a2fc67358583a
546
545
2013-01-15T17:45:07Z
Sourisdudesert
1
/* BGA GUI components */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account: _ current game state & _ interface locking
return true if action is authorized
return false and display an error message if not (display no message if nomessage parameter is true)
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
8e75a75f76580e2f9cb781117094561f3c640a9a
547
546
2013-01-15T17:45:19Z
Sourisdudesert
1
/* Other useful stuff */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account: _ current game state & _ interface locking
return true if action is authorized
return false and display an error message if not (display no message if nomessage parameter is true)
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
53fd25d376669bf4a89e2f54ff0832e2129018b5
548
547
2013-01-15T17:45:33Z
Sourisdudesert
1
/* Players input */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account: _ current game state & _ interface locking
return true if action is authorized
return false and display an error message if not (display no message if nomessage parameter is true)
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
7118f94dfa528ed0ff07820f66e558f73d350d66
549
548
2013-01-15T17:45:45Z
Sourisdudesert
1
/* Other useful stuff */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account: _ current game state & _ interface locking
return true if action is authorized
return false and display an error message if not (display no message if nomessage parameter is true)
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
5b54585df2c6e96126c1a881c0cdf6a6410227b7
550
549
2013-01-15T17:45:57Z
Sourisdudesert
1
/* Access and manipulate the DOM */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account: _ current game state & _ interface locking
return true if action is authorized
return false and display an error message if not (display no message if nomessage parameter is true)
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Notifications ==
== Tooltips ==
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
d847a4298f2d48659e7abac127332ca299483882
Studio
0
49
529
501
2013-01-14T20:17:28Z
Een
3
/* How to join BGA developer team? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
7e6d5b482e09c3b7b35b48a1b07e9ecd44c62b61
Referral
0
11
551
90
2013-01-18T13:35:33Z
Een
3
/* How does this work? */
wikitext
text/x-wiki
[[Category:Help]]
When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]]
== How does this work? ==
Each time a new player creates an account on Board Game Arena from your referrer web address (see below), he becomes one of your '''referees'''. As soon as this referee plays 3 games, you become a member of BGA club.
== How to get referees? ==
To recruit referees, use your personal referrer web address:
{sponsorshipurl}
New players MUST create an account from this web address to become one of your referees.
== How to get many referees? ==
* [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook]
* [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter]
* [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email]
* Publish my personal web address in some forum, send it by MSN, ...
== How many BGA club membership days can I win? ==
As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership.
''Note: your account upgrade will be effective within 24 hours.''
As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership.
... and so on: as your referees number grows you can win many free memberships !
== Referees and multiple accounts ==
It is of course forbidden to create fake referee accounts to win free memberships.
9eb06a83374493fecff6c484c9c14cc24b2bea66
Studio FAQ
0
53
552
421
2013-01-19T13:24:35Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't edit the file, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
b45616fb440438f17118e394471ad3458d8347a5
553
552
2013-01-19T13:24:53Z
Een
3
/* I can't edit the file, it looks like they are readonly. What's happening? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't edit the files for my game, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
bf2990a44d913df03be605bae6635a5712829a0d
554
553
2013-01-19T13:25:09Z
Een
3
/* I can't edit the files for my game, it looks like they are readonly. What's happening? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
28e961be7320545802f150b6304b957d62ffe350
573
554
2013-01-29T21:23:27Z
Sourisdudesert
1
/* How can I provide translation in my language? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== Is there a special way to declare the strings that must be translated? ==
Yes. This declaration is made through transparent functions, that depend on the context.
In javascript files, you should use _( 'My string to translate' ).
In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log).
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
228c35f8d6f017ce425e4137252e104afe9127d0
574
573
2013-01-29T21:23:43Z
Sourisdudesert
1
/* Is there a special way to declare the strings that must be translated? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== It's pretty annoying to log in with multiple users to start a game. Is there some easier way? ==
You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game.
During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective.
You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
e36087c923ca5e0d25409eec810218f72e8c8f9f
576
574
2013-01-29T21:29:11Z
Sourisdudesert
1
/* It's pretty annoying to log in with multiple users to start a game. Is there some easier way? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Is there a quick way to access the database for my current table? ==
Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
71a874d035ff4e8a5dc743da16fbb62b6344e8eb
580
576
2013-01-29T21:44:02Z
Sourisdudesert
1
/* Is there a quick way to access the database for my current table? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the WinSCP client.
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
c0989601e76d0ccf881330ba3f51785befb55fd5
581
580
2013-01-29T21:44:54Z
Sourisdudesert
1
/* What should I use to access the files through SFTP? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
0c5d2fe1d5482e222473398fe6bd8f5bcdb945b0
582
581
2013-01-29T21:52:06Z
Sourisdudesert
1
/* What is the best way to debug? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
d23029c5aaa00274a69aa2bd89e4b30be505699e
Stock
0
97
555
2013-01-21T10:42:32Z
Sourisdudesert
1
Created page with " "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Sto..."
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
aaa3491d40e9f58eb0c33a075306bbfaf932c973
556
555
2013-01-21T10:42:51Z
Sourisdudesert
1
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
(TODO)
259bdd5d57b95bb36ea7250c0d64f61c85daa016
557
556
2013-01-23T06:45:58Z
Sourisdudesert
1
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
_ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
_ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
_ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
_ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
596e2d334136943a584826bf495ae8cf793d5510
559
557
2013-01-26T04:58:23Z
Pikiou
1872
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
_ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
_ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
_ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
_ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
d9a22a4260d98df2ad1fd5eefe00d825b91c94a7
Gamehelpintheyearofthedragon
0
51
558
227
2013-01-25T07:25:06Z
Chefneil
2211
/* End-of-game Scoring */
wikitext
text/x-wiki
=== End-of-round Scoring ===
* 1 point for each palace.
* 1 point For each court lady.
* 1 point For each privilege. (Small privilege = 1 point; Large privilege = 2 points)
=== End-of-game Scoring ===
* 2 points for each person tile.
* For each monk: score [number of Buddhas] x [number of floors] points.
* Each player sells back to the supply all of his rice and fireworks tiles for 2 yuan each.Afterward, each player earns 1 victory point for every 3 yuan he possesses.
d14091f98a1adfed010f5ef619850821e1c47d1b
Game interface logic: yourgamename.js
0
88
560
550
2013-01-29T20:16:07Z
Sourisdudesert
1
/* Tooltips */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account: _ current game state & _ interface locking
return true if action is authorized
return false and display an error message if not (display no message if nomessage parameter is true)
'''this.ajaxcall()'''
TODO
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Notifications ==
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
cca113c65beb3f4b496694319e19911ae4adbf02
561
560
2013-01-29T20:23:45Z
Sourisdudesert
1
/* Players input */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Notifications ==
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
7c1c1a5b909b7d3a6974119c27e7cb3648bd91d5
571
561
2013-01-29T21:21:55Z
Sourisdudesert
1
/* Access and manipulate the DOM */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Notifications ==
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
89b39331514986dad84a1f8c6f5d7ad8ad561b3e
572
571
2013-01-29T21:22:21Z
Sourisdudesert
1
/* Access and manipulate the DOM */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Notifications ==
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
593b196f904b35192fcc41acc623cc34b71e88b9
Main game logic: yourgamename.game.php
0
86
562
518
2013-01-29T20:30:13Z
Sourisdudesert
1
/* Translations */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
4d7d4744233cd8afd5bd1c1aa6db76ab3570a8d1
563
562
2013-01-29T20:38:07Z
Sourisdudesert
1
/* Manage player scores and Tie breaker */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods:
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
5fbea32b7752c400ce2e16ca6200144df516f94d
586
563
2013-01-29T22:10:38Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
IMPORTANT: BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
51b1fdd1370f93c3b2c675b52245872c70fa5754
587
586
2013-01-29T22:11:00Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
6502226df993ec63c7c972714147ec92d7471ffe
588
587
2013-01-29T22:11:07Z
Sourisdudesert
1
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
6282c3822e4e213200925c1cc8200f6af6ed3443
589
588
2013-01-29T22:12:43Z
Sourisdudesert
1
/* Notify players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
f2ac5c9d3fd78ef14e0c1ce46b4d58df770dcba0
590
589
2013-01-29T22:14:15Z
Sourisdudesert
1
/* Managing errors and exceptions */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
1185bc779ecad94a1a233b0387229b9f919a6527
Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl
0
98
564
2013-01-29T20:53:10Z
Sourisdudesert
1
Created page with "These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>,..."
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "reversi_reversi.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
ab1fa2414a3eb4c232aea1ee4034fcacd33db6a6
565
564
2013-01-29T20:59:20Z
Sourisdudesert
1
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "reversi_reversi.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
1cbe6c9723a2d6bd6ac9ad8d975396e73c9c7645
566
565
2013-01-29T21:03:29Z
Sourisdudesert
1
/* Blocks */
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "reversi_reversi.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
Using "blocks", you can repeat a piece of HTML from your template several time.
You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares:
<pre>
(in reversi_reversi.tpl)
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
<div id="discs">
</div>
</div>
(in reversi.view.php)
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
be61b0d8430efd6be334f471987d1957b13d11e1
567
566
2013-01-29T21:03:49Z
Sourisdudesert
1
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "hearts_hearts.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
Using "blocks", you can repeat a piece of HTML from your template several time.
You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares:
<pre>
(in reversi_reversi.tpl)
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
<div id="discs">
</div>
</div>
(in reversi.view.php)
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
b72e8c036aae4063866997eef8e29091924aa682
568
567
2013-01-29T21:06:50Z
Sourisdudesert
1
/* Blocks */
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "hearts_hearts.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
Using "blocks", you can repeat a piece of HTML from your template several time.
You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares:
<pre>
(in reversi_reversi.tpl)
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
<div id="discs">
</div>
</div>
(in reversi.view.php)
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Explanations:
* You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square".
* In your view, you declare your block using "begin_block" method.
* Then, you can insert as many block as you want to, using "insert_block" method.
The insert_block method takes 2 parameters:
* the name of the block to insert.
* an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP).
01e70246e836e8ea7fdc7274434f54f6b8027375
569
568
2013-01-29T21:15:22Z
Sourisdudesert
1
/* Blocks */
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "hearts_hearts.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
Using "blocks", you can repeat a piece of HTML from your template several time.
You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares:
<pre>
(in reversi_reversi.tpl)
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
<div id="discs">
</div>
</div>
(in reversi.view.php)
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Explanations:
* You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square".
* In your view, you declare your block using "begin_block" method.
* Then, you can insert as many block as you want to, using "insert_block" method.
The insert_block method takes 2 parameters:
* the name of the block to insert.
* an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP).
== Nested blocks ==
You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it:
<pre>
(In template file)
<!-- BEGIN player -->
<div class="miniboard" id="miniboard_{PLAYER_ID}">
<div class="card_places">
<!-- BEGIN card_place -->
<div id="card_place_{PLAYER_ID}_{PLACE_ID}">
</div>
<!-- END card_place -->
</div>
</div>
<!-- END player -->
(In view file)
$this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first
$this->page->begin_block( "mygame_mygame.tpl", "player" );
foreach( $players as $player_id => $player )
{
// Important: nested block must be reset here, otherwise the second player miniboard will
// have 8 card_place, the third will have 12 card_place, and so one...
$this->page->reset_subblocks( 'card_place' );
for( $i=1; $i<=4; $i++ )
{
$this->page->insert_block( "card_place", array(
'PLAYER_ID' => $player_id,
'PLACE_ID' => $i
);
}
$this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id );
}
</pre>
b6cd67e2292dd8601b8c6a6f00338aa000a8901b
570
569
2013-01-29T21:19:50Z
Sourisdudesert
1
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "hearts_hearts.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
Using "blocks", you can repeat a piece of HTML from your template several time.
You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares:
<pre>
(in reversi_reversi.tpl)
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
<div id="discs">
</div>
</div>
(in reversi.view.php)
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Explanations:
* You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square".
* In your view, you declare your block using "begin_block" method.
* Then, you can insert as many block as you want to, using "insert_block" method.
The insert_block method takes 2 parameters:
* the name of the block to insert.
* an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP).
== Nested blocks ==
You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it:
<pre>
(In template file)
<!-- BEGIN player -->
<div class="miniboard" id="miniboard_{PLAYER_ID}">
<div class="card_places">
<!-- BEGIN card_place -->
<div id="card_place_{PLAYER_ID}_{PLACE_ID}">
</div>
<!-- END card_place -->
</div>
</div>
<!-- END player -->
(In view file)
$this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first
$this->page->begin_block( "mygame_mygame.tpl", "player" );
foreach( $players as $player_id => $player )
{
// Important: nested block must be reset here, otherwise the second player miniboard will
// have 8 card_place, the third will have 12 card_place, and so one...
$this->page->reset_subblocks( 'card_place' );
for( $i=1; $i<=4; $i++ )
{
$this->page->insert_block( "card_place", array(
'PLAYER_ID' => $player_id,
'PLACE_ID' => $i
);
}
$this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id );
}
</pre>
== Javascript templates ==
For game elements that come and go from the game area, we suggest you to define a Javascript template.
A Javascript template is defined in your template file like this:
(Reversi Token from Reversi example):
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: a section for javascript templates is already available at the end of your template skeleton file.
Then, you can use this javascript template to insert this piece of HTML in your game interface, like this:
<pre>
dojo.place( this.format_block( 'jstpl_disc', {
xy: x+''+y,
color: color
} ) , 'discs' );
</pre>
9806b9dfa29915aec140a1017843edaa96b9cd79
Studio
0
49
575
529
2013-01-29T21:25:00Z
Sourisdudesert
1
/* BGA Studio user guide */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
71afcb42b7cf6027b4c429ccf53881bf70a0dfc5
Tools and tips of BGA Studio
0
99
577
2013-01-29T21:31:32Z
Sourisdudesert
1
Created page with "== Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 pla..."
wikitext
text/x-wiki
== Starting a game in one click ==
To start a game:
* Create a new table with your game.
* If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table.
* Click on "Express Start".
== Stopping a game in one click ==
* Click on the "quit" icon on the top right of the screen.
* Click on "Express Stop".
== Switching between users ==
when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective.
== Access to game database ==
Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game.
== Input/Output debugging section ==
4b27048eb61349acf7cff6a912e8cd7df429beee
578
577
2013-01-29T21:39:56Z
Sourisdudesert
1
/* Input/Output debugging section */
wikitext
text/x-wiki
== Starting a game in one click ==
To start a game:
* Create a new table with your game.
* If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table.
* Click on "Express Start".
== Stopping a game in one click ==
* Click on the "quit" icon on the top right of the screen.
* Click on "Express Stop".
== Switching between users ==
when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective.
== Access to game database ==
Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game.
== Save & restore state ==
Using links of this section, you can save the complete current (database) state of your game, then restore it later.
This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine.
We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations.
Limits:
* the "restore" function does not work anymore when the game is over.
* a saved situation from a given table cannot be restored in another table.
* when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually.
== Input/Output debugging section ==
This section shows you:
* The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">"
* The notifications received by your game interface. Notifications (inputs) begins with "<".
Note: if you click on some notification title, you can resend it immediately to the user interface.
607228e76ddee8545782d4adb3003f0e4507cbc9
579
578
2013-01-29T21:42:54Z
Sourisdudesert
1
wikitext
text/x-wiki
== Starting a game in one click ==
To start a game:
* Create a new table with your game.
* If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table.
* Click on "Express Start".
== Stopping a game in one click ==
* Click on the "quit" icon on the top right of the screen.
* Click on "Express Stop".
== Switching between users ==
when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective.
== Access to game database ==
Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game.
== Save & restore state ==
Using links of this section, you can save the complete current (database) state of your game, then restore it later.
This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine.
We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations.
Limits:
* the "restore" function does not work anymore when the game is over.
* a saved situation from a given table cannot be restored in another table.
* when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually.
== Input/Output debugging section ==
This section shows you:
* The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">"
* The notifications received by your game interface. Notifications (inputs) begins with "<".
Note: if you click on some notification title, you can resend it immediately to the user interface.
== Run from the chat ==
On BGA Studio, you can directly run a PHP method from the chat.
For example, if on your PHP you have this method:
<pre>
function giveMoneyToPlayer($player_id, $amount)
{
// Do some stuff
}
</pre>
You can call this method directly from the chat like this: "giveMoneyToCurrentPlayer(2564,2)".
5830ee3dfd380fce44ae7cbc5223a65eb4e15b54
Practical debugging
0
100
583
2013-01-29T21:53:08Z
Sourisdudesert
1
Created page with " This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Debu..."
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the Studio backoffice.
== Debugging my PHP game logic (or my view) ==
Debugging PHP is most of the time easy
== Debugging my HTML/CSS layout ==
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
aa44fcaeaecdd7c548e30cbeacca25903f08191c
584
583
2013-01-29T21:54:35Z
Sourisdudesert
1
/* Debugging my game when it cannot start */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Debugging PHP is most of the time easy
== Debugging my HTML/CSS layout ==
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
8d4dc06fe5c513252e4a5c75711404b51879ba28
585
584
2013-01-29T22:04:44Z
Sourisdudesert
1
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a "die('ok');" PHP statement right after the PHP I am developing/debugging. This way, the PHP request will stop immediately, nothing will be commited to the database, and the game initial situation will remains.
== Debugging my HTML/CSS layout ==
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
d8fb000e12a9e4fd6921ed6bf0c2012cc574c113
591
585
2013-01-29T22:18:09Z
Sourisdudesert
1
/* Debugging my PHP game logic (or my view) */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
== Debugging my HTML/CSS layout ==
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the server side (PHP), you can use one of these:
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
c603f203a8e5dfd46b7ecdaa18e21ff21f0dd7ec
592
591
2013-01-29T22:29:50Z
Sourisdudesert
1
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
=== Browsers ===
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tooltip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
0cafffec180d2a8f54155d7119ff55c2acbfe733
593
592
2013-01-29T22:30:46Z
Sourisdudesert
1
/* Tools */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tooltip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
c223b0d05f92488930d83663bc3e2977ceac439f
594
593
2013-01-29T22:30:57Z
Sourisdudesert
1
/* General tooltip for debugging */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
f446e2bbceb1f7a0c2685da8aa1eccacf627d645
595
594
2013-01-29T22:39:27Z
Sourisdudesert
1
/* Debugging my HTML/CSS layout */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
09a63b6229f62026d949b7ede710534f5e0b36cc
596
595
2013-01-29T22:41:41Z
Sourisdudesert
1
/* Debugging my HTML/CSS layout */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
* alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
4a98b70a461dfb2203e4ef49ab559c0fd396ff8f
597
596
2013-01-29T22:41:56Z
Sourisdudesert
1
/* What is the best way to debug? */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
== Some frequent errors ==
== What is the best way to debug? ==
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
7acea4428a85c6fe896dc1ade348a17d3a5e9108
598
597
2013-01-29T22:48:50Z
Sourisdudesert
1
/* Debugging my Javascript game interface logic */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
== What is the best way to debug? ==
On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
=== Some frequent errors ===
; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
06380bd3a0144fcea81636911402c0ed7e3daeba
599
598
2013-01-29T22:49:08Z
Sourisdudesert
1
/* What is the best way to debug? */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
b7e2f0def9efdc1c661b1f8a9e18e95986cf3546
600
599
2013-01-29T22:49:46Z
Sourisdudesert
1
/* Some frequent errors */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
As these functions are not consequences of a user action, there is no current player defined.
As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
a275e649f9e2640946cd8398d7ec6b216a0bc8c7
Game database model: dbmodel.sql
0
92
601
490
2013-01-30T13:44:45Z
Sourisdudesert
1
/* Default tables */
wikitext
text/x-wiki
In this file you specify the database schema of your game.
This file contains SQL queries that will be executed during the creation of your game table.
Note: you can't change the database schema during the game.
== Create your schema ==
To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file.
== Default tables ==
Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player.
You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code).
You may add columns to "player" table. This is very practical to add simple values associated with players.
Example:
<pre>
ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7';
</pre>
For your information, the useful columns of default "player" table are:
* player_no: the index of player in natural playing order.
* player_id
* player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods)
* player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores.
* player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game (see also: [[Main_game_logic:_yourgamename.game.php#Manage_player_scores_and_Tie_breaker|Manage_player_scores_and_Tie_breaker]])
55928f7428de62d98335489cb1b48e7a5e837ad4
Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl
0
98
602
570
2013-01-30T13:51:18Z
Sourisdudesert
1
/* Javascript templates */
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "hearts_hearts.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
Using "blocks", you can repeat a piece of HTML from your template several time.
You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares:
<pre>
(in reversi_reversi.tpl)
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
<div id="discs">
</div>
</div>
(in reversi.view.php)
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Explanations:
* You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square".
* In your view, you declare your block using "begin_block" method.
* Then, you can insert as many block as you want to, using "insert_block" method.
The insert_block method takes 2 parameters:
* the name of the block to insert.
* an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP).
== Nested blocks ==
You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it:
<pre>
(In template file)
<!-- BEGIN player -->
<div class="miniboard" id="miniboard_{PLAYER_ID}">
<div class="card_places">
<!-- BEGIN card_place -->
<div id="card_place_{PLAYER_ID}_{PLACE_ID}">
</div>
<!-- END card_place -->
</div>
</div>
<!-- END player -->
(In view file)
$this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first
$this->page->begin_block( "mygame_mygame.tpl", "player" );
foreach( $players as $player_id => $player )
{
// Important: nested block must be reset here, otherwise the second player miniboard will
// have 8 card_place, the third will have 12 card_place, and so one...
$this->page->reset_subblocks( 'card_place' );
for( $i=1; $i<=4; $i++ )
{
$this->page->insert_block( "card_place", array(
'PLAYER_ID' => $player_id,
'PLACE_ID' => $i
);
}
$this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id );
}
</pre>
== Javascript templates ==
For game elements that come and go from the game area, we suggest you to define a Javascript template.
A Javascript template is defined in your template file like this:
(Reversi Token from Reversi example):
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: a section for javascript templates is already available at the end of your template skeleton file.
Then, you can use this javascript template to insert this piece of HTML in your game interface, like this:
<pre>
dojo.place( this.format_block( 'jstpl_disc', {
xy: x+''+y,
color: color
} ) , 'discs' );
</pre>
== How to access game information from .view.php? ==
From your .view.php, you can access the following:
=== Access current player id===
<pre>
global $g_user;
$current_player_id = $g_user->get_id();
</pre>
=== Access game object ===
In your view file, "$this->game" contains an instance of your main game class.
Example:
<pre>
// Access to some game elements description described in your "material.inc.php":
$my_cards_types = $this->game->card_types;
// Access to any (public) method defined in my .game.php file:
$result = $this->game->myMethod();
</pre>
a1db3a68a1c6b558482b31c4766efcb3c6170a16
Translations
0
94
603
534
2013-01-30T14:00:36Z
Sourisdudesert
1
/* Focus on translating notifications */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
00b876af979e40df1604bdaf14081b503740bd63
604
603
2013-01-30T14:08:44Z
Sourisdudesert
1
/* WARNING: how to make sure your strings will be translated */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== How to not make translators crazy ;) ==
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
<pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre>
Write instead:
<pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre>
(or the equivalent "dojo.string.substitute" in Javascript)
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short string.
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
6f088dd77b603414b4986ec781e0714c6b6ca381
605
604
2013-01-30T14:09:03Z
Sourisdudesert
1
/* How to not make translators crazy ;) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== How to not make translators crazy ;) ==
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
<pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre>
Write instead:
<pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre>
(or the equivalent "dojo.string.substitute" in Javascript)
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings.
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
5342d4acfd2ce7de3b9b024bdee754ec12cbe55f
606
605
2013-01-30T14:11:52Z
Sourisdudesert
1
/* How to not make translators crazy ;) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== How to not make translators crazy ;) ==
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
<pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre>
Write instead:
<pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre>
(or the equivalent "dojo.string.substitute" in Javascript)
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings.
* The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate.
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
437b64de7275fe16f6a09023d10a92b7ab0303b2
Game interface logic: yourgamename.js
0
88
607
572
2013-01-30T14:12:52Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
f4a705f0f672ce8dddadba6c9f4d613dd937ae54
608
607
2013-01-30T14:21:47Z
Sourisdudesert
1
/* Notifications */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
9a8fdfb42e8b8eb4ec315d1daf3cb4d45f9e680d
609
608
2013-01-30T14:27:59Z
Sourisdudesert
1
/* Subscribe to notifications */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
== Animations ==
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
4c7fc3933a944503c6d3bffcdd3a28fe399ce52c
610
609
2013-01-30T14:43:43Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
ceee517a59f3dc740a50da1f396cfc171f5e8cf3
611
610
2013-01-30T14:51:01Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
9b8fb6b0cdfd751a4df6d848620ba468d2c8bcc2
612
611
2013-01-30T14:52:08Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
ff91a04387ccb6ce0a83b2057d73d2f3b02aceb2
613
612
2013-01-30T14:58:55Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
f113c6f0688a5c8675268b06b776a472e8e296e6
614
613
2013-01-30T15:00:13Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
8a38d623f326ef8eba093681c87adc036cbbcc11
615
614
2013-01-30T15:07:09Z
Sourisdudesert
1
/* Moving elements */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
f585ef408be1bd33f808044adf1ccf799dc50695
616
615
2013-01-30T15:08:50Z
Sourisdudesert
1
/* Other useful stuff */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
8b08708d91b15ed204ebd2b648b54676117e1b7d
617
616
2013-01-30T15:08:59Z
Sourisdudesert
1
/* General tips */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
34566293e7a72a0b6122ff14fd675a9a43dc1aa2
618
617
2013-01-30T15:19:59Z
Sourisdudesert
1
/* Other useful stuff */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
412a63f4c33407628ed1d60a616f31f7c8f1cc43
619
618
2013-01-30T15:20:36Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
1c8e0371e586802deb58127e413bdc5396e52fec
620
619
2013-01-30T15:20:52Z
Sourisdudesert
1
/* Other useful stuff */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
b36c6cc0e7326219304189b189b0bc902479c611
621
620
2013-01-30T15:22:21Z
Sourisdudesert
1
/* Dialogs, warning messages, confirmation dialogs, ... */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
26121d2968fe9d01fe23fe8daff1cf93e815eeaa
622
621
2013-01-30T15:30:44Z
Sourisdudesert
1
/* Dialogs, warning messages, confirmation dialogs, ... */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
da65aad9c96ea34a94096025ba4eb7d0ade5f6d6
623
622
2013-01-30T15:38:14Z
Sourisdudesert
1
/* Dialogs, warning messages, confirmation dialogs, ... */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
=== Scoring dialogs ===
TODO
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
065726dd9b1f8325cdbbf4cceabb97f1869edd0a
624
623
2013-01-30T15:41:40Z
Sourisdudesert
1
/* Dialogs */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
</pre>
=== Scoring dialogs ===
TODO
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
fb2368d30850f91de0df598317f17804ad420937
625
624
2013-01-30T15:43:40Z
Sourisdudesert
1
/* Dialogs */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
=== Scoring dialogs ===
TODO
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
4de87503c1d29276dafd667781f2d379528e7581
626
625
2013-01-30T15:45:40Z
Sourisdudesert
1
/* Dialogs */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
TODO
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
65ee871aec9432a99069caac08f4127d8ca0d83d
627
626
2013-01-30T15:48:21Z
Sourisdudesert
1
/* Scoring dialogs */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
370fe31d6e015e611d22df85d8b741b7c9e7ea13
628
627
2013-01-30T16:09:54Z
Sourisdudesert
1
/* Scoring dialogs */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
91ac3f1c2bed80d7d77eae390f6293ca4b66848f
629
628
2013-01-30T16:12:45Z
Sourisdudesert
1
/* BGA GUI components */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
3cdee1e01b47aa1e56b73b29b4d01a823ae07118
644
629
2013-02-12T12:22:39Z
Sourisdudesert
1
/* General tips */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
4724100d9aa96ce01e65d3b388664799dde876b1
Practical debugging
0
100
630
600
2013-01-30T16:17:01Z
Sourisdudesert
1
/* Some frequent errors */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
As these functions are not consequences of a user action, there is no current player defined.
As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
=== when refreshing the web page, the interface remains on "Application loading..." ===
In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load.
To find this error, check if there is an error message in the Javascript console (F12).
If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition.
8a99f335a3ab6c99af2563f71f88bdc43ea419d6
631
630
2013-01-30T16:31:34Z
Sourisdudesert
1
/* Some frequent errors */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
As these functions are not consequences of a user action, there is no current player defined.
As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
=== when refreshing the web page, the interface remains on "Application loading..." ===
In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load.
To find this error, check if there is an error message in the Javascript console (F12).
If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition.
=== When I do a move, I got "Move recorded, waiting for update ..." forever ===
"Move recorded" means that your ajaxcall request has been sent to the server and returned normally.
"Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did.
If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code.
=== Some player action is triggered randomly when I click somewhere on the game area ===
You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area.
Most of the time it happens in this situation, when my_object element does not exists:
<pre>
dojo.connect( $("my_object"), "onclick", this, function() {
...
}
</pre>
To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not.
=== Javascript does not know how to sum two numbers ===
Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers.
As a result:
<pre>
var i=1;
i += notif.args.increment; // With notif.args.increment='1'
alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings !
</pre>
To solve this, to hesitate to use the "toint" function:
<pre>
var i=1;
i += toint( notif.args.increment ); // With notif.args.increment='1'
alert( i ); // i=2 :)
</pre>
33d94ad6544cac38815e06aab6deb73b0cd2d016
632
631
2013-01-30T16:35:03Z
Sourisdudesert
1
/* Javascript does not know how to sum two numbers */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
As these functions are not consequences of a user action, there is no current player defined.
As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
=== when refreshing the web page, the interface remains on "Application loading..." ===
In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load.
To find this error, check if there is an error message in the Javascript console (F12).
If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition.
=== When I do a move, I got "Move recorded, waiting for update ..." forever ===
"Move recorded" means that your ajaxcall request has been sent to the server and returned normally.
"Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did.
If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code.
=== Some player action is triggered randomly when I click somewhere on the game area ===
You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area.
Most of the time it happens in this situation, when my_object element does not exists:
<pre>
dojo.connect( $("my_object"), "onclick", this, function() {
...
}
</pre>
To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not.
=== Javascript does not know how to sum two numbers ===
Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers.
As a result:
<pre>
var i=1;
i += notif.args.increment; // With notif.args.increment='1'
alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings !
</pre>
To solve this, to hesitate to use the "toint" function:
<pre>
var i=1;
i += toint( notif.args.increment ); // With notif.args.increment='1'
alert( i ); // i=2 :)
</pre>
=== Javascript: do not use substr with negative numbers ===
To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE:
<pre>
var three_last_characters = string.substr( -3 ); // Wrong
var three_last_characters = string.slice( -3 ); // Correct
</pre>
cf42daf00fb7be404a4a30ec9f179847d5a069cc
Stock
0
97
633
559
2013-02-02T08:55:38Z
Sourisdudesert
1
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
_ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
_ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
_ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
_ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
16282ee586f0e8c2046670ca09ab3d2e371cf099
643
633
2013-02-12T12:11:45Z
Sourisdudesert
1
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
_ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
_ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
_ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
_ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
47c1cb6415f093e75bceb1a338885062667c2054
Game interface stylesheet: yourgamename.css
0
96
634
520
2013-02-04T14:48:42Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the CSS stylesheet of your game User Interface.
Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript.
Usually, you are using CSS to:
1°) define the overall layout of your game
(ex: place the board on the top left, place player's hand beside, place the deck on the right, ...).
2°) create your CSS-sprites:
All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly.
Example:
<pre>
Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image):
.white_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: 0px 0px;
}
.black_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: -20px 0px;
}
.token {
width: 20px;
height: 20px;
background-repeat: none;
}
</pre>
3°) ... anything else:
It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query).
This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily.
Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary.
Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them.
9820cd9a56bfee0746b394fc31f1382787b601a5
Gamehelpcantstop
0
35
635
170
2013-02-07T04:14:07Z
Karl
2334
wikitext
text/x-wiki
Can't Stop is a very easy and fast game!
'''How to play'''
Roll 4 standard dice and then choose the sums of any 2 dice to advance your position on the board. You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have fewer.
'''The object of the game is''' to reach and cover 3 peaks of these columns!
欲罷不能
如何進行遊戲
首先擲出四顆骰子,之後把四顆骰子兩兩分組配成可以搭配的任意數字(2~12),之後選擇其中一種配對執行。
執行時你可以擁有三個暫時的標記物可以作為前進的工具(此回合超過第三個就不能選該組合中的該項數值,但是其中一項可以前進即可選擇,另外一總組合則視同放棄)
重複以上動作直到你覺得這回合你前進已經夠了或是擲出你沒有辦法前進的骰子點數組合則該回合結束
若是自己喊出「夠了」則在現有的暫時標記物的位置換成自己的標記物輪下一人進行
若是因為擲出不能前進的骰子組合則是本回合前進的格數全部作廢依然換下一人進行回合
遊戲中使用的是兩個六面骰,依照組合的出現機率不同,在不同組合上要攻頂的需求步數也不同(例如7就需要最多格,因為他的出現率最高,相對的比較難出現的2.12就只需要短短的三格)
遊戲獲勝條件是其中有一人佔領了三條路線後則遊戲結束,由佔領三條路線的人獲勝
eb25daa5eaeda4fa4f83b74e41bcddcae0491261
Deck
0
101
636
2013-02-11T16:56:57Z
Sourisdudesert
1
Created page with ""Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following fea..."
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
99108eb430d4ddf064ecc1abd63107dd0fa58251
637
636
2013-02-11T17:05:25Z
Sourisdudesert
1
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck general principles ==
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
3fe6de7e682508ff987b79aa27af2393f512b96d
638
637
2013-02-11T17:23:59Z
Sourisdudesert
1
/* Deck general principles */
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
* '''type''' and '''type_arg''': These two values defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can start using our "Deck" object. In general, the first
5b42f3001a9bbf08e8e856a5d573d6ffd80ed60b
639
638
2013-02-11T17:35:46Z
Sourisdudesert
1
/* Deck overview */
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
=== The 5 properties of each card ===
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card.
* '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?).
* '''location''' and '''location_arg''': These two values defines where is the card at now.
id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.
'''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
'''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
'''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer.
You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:
* 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
* 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
* 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").
Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.
=== Create a new Deck component ===
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can start using our "Deck" object. In general, the first
dbeb5611d5db3a1ebe6fe5ed93f5151f1197b857
640
639
2013-02-11T17:39:39Z
Sourisdudesert
1
/* Create a new Deck component */
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
=== The 5 properties of each card ===
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card.
* '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?).
* '''location''' and '''location_arg''': These two values defines where is the card at now.
id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.
'''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
'''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
'''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer.
You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:
* 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
* 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
* 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").
Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.
=== Create a new Deck component ===
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method.
"Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts":
<pre>
// Create cards
$cards = array();
foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club
{
for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A
{
$cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1);
}
}
$this->cards->createCards( $cards, 'deck' );
</pre>
As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument).
bf27635292e5f1fa021037833d79d2eb48e3c25a
641
640
2013-02-11T17:46:47Z
Sourisdudesert
1
/* Create a new Deck component */
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
=== The 5 properties of each card ===
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card.
* '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?).
* '''location''' and '''location_arg''': These two values defines where is the card at now.
id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.
'''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
'''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
'''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer.
You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:
* 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
* 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
* 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").
Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.
=== Create a new Deck component ===
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method.
"Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts":
<pre>
// Create cards
$cards = array();
foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club
{
for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A
{
$cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1);
}
}
$this->cards->createCards( $cards, 'deck' );
</pre>
As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument).
Now, you are ready to use "Deck"!
=== Simple examples using Deck ===
(Most examples are from "Hearts" game)
<pre>
// In "getAllDatas', we need to send to the current player all the cards he has in hand:
$result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id );
</pre>
<pre>
// At some time we want to check if all the cards (52) are in player's hands:
if( $this->cards->countCardInLocation( 'hand' ) == 52 )
// do something
</pre>
<pre>
// When a player plays a card in front of him on the table:
$this->cards->moveCard( $card_id, 'cardsontable', $player_id );
// Note the use of the custom location 'cardsontable' here to keep track of cards on the table.
</pre>
<pre>
// This is a new hand: let's gather all cards from everywhere in the deck:
$this->cards->moveAllCardsInLocation( null, "deck" );
// And then shuffle the deck
$this->cards->shuffle( 'deck' );
// And then deal 13 cards to each player
// Deal 13 cards to each players
// Create deck, shuffle it and give 13 initial cards
$players = self::loadPlayersBasicInfos();
foreach( $players as $player_id => $player )
{
$cards = $this->cards->pickCards( 13, 'deck', $player_id );
// Notify player about his cards
self::notifyPlayer( $player_id, 'newHand', '', array(
'cards' => $cards
) );
}
// Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;)
</pre>
d01c941c833ffd3e1318e0ad694112c6c46f2afa
650
641
2013-02-13T17:02:33Z
Sourisdudesert
1
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
=== The 5 properties of each card ===
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card.
* '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?).
* '''location''' and '''location_arg''': These two values defines where is the card at now.
id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.
'''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
'''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
'''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer.
You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:
* 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
* 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
* 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").
Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.
=== Create a new Deck component ===
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method.
"Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts":
<pre>
// Create cards
$cards = array();
foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club
{
for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A
{
$cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1);
}
}
$this->cards->createCards( $cards, 'deck' );
</pre>
As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument).
Now, you are ready to use "Deck"!
=== Simple examples using Deck ===
(Most examples are from "Hearts" game)
<pre>
// In "getAllDatas', we need to send to the current player all the cards he has in hand:
$result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id );
</pre>
<pre>
// At some time we want to check if all the cards (52) are in player's hands:
if( $this->cards->countCardInLocation( 'hand' ) == 52 )
// do something
</pre>
<pre>
// When a player plays a card in front of him on the table:
$this->cards->moveCard( $card_id, 'cardsontable', $player_id );
// Note the use of the custom location 'cardsontable' here to keep track of cards on the table.
</pre>
<pre>
// This is a new hand: let's gather all cards from everywhere in the deck:
$this->cards->moveAllCardsInLocation( null, "deck" );
// And then shuffle the deck
$this->cards->shuffle( 'deck' );
// And then deal 13 cards to each player
// Deal 13 cards to each players
// Create deck, shuffle it and give 13 initial cards
$players = self::loadPlayersBasicInfos();
foreach( $players as $player_id => $player )
{
$cards = $this->cards->pickCards( 13, 'deck', $player_id );
// Notify player about his cards
self::notifyPlayer( $player_id, 'newHand', '', array(
'cards' => $cards
) );
}
// Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;)
</pre>
== Deck component reference ==
=== Initializing Deck component ===
'''init( $table_name )'''
Initialize the Deck component.
Argument:
* table_name: name of the DB table used by this Deck component.
Must be called before any other Deck method.
Usually, init is called in your game constructor.
Example with Hearts:
<pre>
function Hearts( )
{
(...)
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
}
</pre>
'''createCards( $cards, $location='deck', $location_arg=null )'''
Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game.
"cards" describe all cards that need to be created. "cards" is an array with the following format:
<pre>
// Create 1 card of type "1" with type_arg=99,
// and 4 cards of type "2" with type_arg=12,
// and 2 cards of type "3" with type_arg=33
$cards = array(
array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ),
array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ),
array( 'type' => 3, 'type_arg' => 33, nbr' => 2 )
...
);
</pre>
Note: During the "createCards" process, Deck generate unique IDs for all card items.
Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one.
If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location.
=== Card standard format ===
When Deck component methods are returning one or several cards, the following format is used:
<pre>
array(
'id' => .., // the card ID
'type' => .., // the card type
'type_arg' => .., // the card type argument
'location' => .., // the card location
'location_arg' => .. // the card location argument
);
<pre>
=== Picking cards ===
'''pickCard( $location, $player_id )'''
Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player.
Return the card picked or "null" if there are no more card in given location.
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCards( $nbr, $location, $player_id )'''
Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player.
Return an array with the cards picked, or "null" if there are no more card in given location.
Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location.
This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked.
'''pickCardForLocation( $from_location, $to_location, $location_arg=0 )'''
This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location.
_ from_location is the "pile" style location from where you are picking a card.
_ to_location is the location where you will place the card picked.
_ if "location_arg" is specified, the card picked will be set with this "location_arg".
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )'''
This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location.
_ from_location is the "pile" style location from where you are picking some cards.
_ to_location is the location where you will place the cards picked.
_ if "location_arg" is specified, the cards picked will be set with this "location_arg".
_ if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call.
This method supports auto-reshuffle (see "auto-reshuffle" below).
=== Moving cards ===
'''moveCard( $card_id, $location, $location_arg=0 )'''
Move the specific card to given location.
_ card_id: ID of the card to move.
_ location: location where to move the card.
_ location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0.
'''moveCards( $cards, $location, $location_arg )'''
Move the specific cards to given location.
_ cards: an array of IDs of cards to move.
_ location: location where to move the cards.
_ location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0.
'''insertCard( $card_id, $location, $location_arg )'''
Move a card to a specific "pile" location where card are ordered.
If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location.
(note: insertCardOnExtremePosition method below is more useful in most of the case)
'''insertCardOnExtremePosition( $card_id, $location, $bOnTop )'''
Move a card on top or at bottom of given "pile" type location.
'''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )'''
Move all cards in specified "from" location to given location.
_ from_location: where to take the cards
_ to_location: where to put the cards
_ from_location (optional): if specified, only cards with given "location_arg" are moved.
_ to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero.
Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below.
'''moveAllCardsInLocationKeepOrder( $from_location, $to_location )'''
Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards.
'''playCard( $card_id )'''
Move specified card at the top of the "discard" location.
Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true )
=== Get cards informations ===
'''getCard( $card_id )'''
Get specific card information.
Return null if this card is not found.
'''getCards( $cards_array )'''
Get specific cards information.
cards_array is an array of cards ID.
If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception.
'''getCardsInLocation( $location, $location_arg = null, $order_by = null )'''
Get all cards in specific location, as an array. Return an empty array if the location is empty.
_ location (string): the location where to get the cards.
_ location_arg (optional): if specified, return only cards with the specified "location_arg".
_ order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type".
'''countCardInLocation( $location, $location_arg=null )'''
Return the number of cards in specified location.
_ location (string): the location where to count the cards.
_ location_arg (optional): if specified, count only cards with the specified "location_arg".
'''countCardsInLocations()'''
Return the number of cards in each location of the game.
The method returns an associative array with the format "location" => "number of cards".
Example:
<pre>
array(
'deck' => 12,
'hand' => 21,
'discard' => 54,
'ontable' => 3
);
</pre>
'''countCardsByLocationArgs( $location )'''
Return the number of cards in each "location_arg" for the given location.
The method returns an associative array with the format "location_arg" => "number of cards".
Example: count the number of cards in each player's hand:
<pre>
countCardsByLocationArgs( 'hand' );
// Result:
array(
122345 => 5, // player 122345 has 5 cards in hand
123456 => 4 // and player 123456 has 4 cards in hand
);
</pre>
'''getPlayerHand( $player_id )'''
Get all cards in given player hand.
Note: This is an alias for:
getCardsInLocation( "hand", $player_id )
'''getCardOnTop( $location )'''
Get the card on top of the given ("pile" style) location, or null if the location is empty.
Note that the card pile won't be "auto-reshuffled" if there is no more card available.
'''getCardsOnTop( $nbr, $location )'''
Get the "$nbr" cards on top of the given ("pile" style) location.
The method return an array with at most "$nbr" elements (or a void array if there is no card in this location).
Note that the card pile won't be "auto-reshuffled" if there is not enough cards available.
'''getExtremePosition( $bGetMax ,$location )'''
(rarely used)
Get the position of cards at the top of the given location / at the bottom of the given location.
Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location).
If bGetMax=true, return the location of the top card of the pile.
If bGetMax=false, return the location of the bottom card of the pile.
'''getCardsOfType( $type, $type_arg=null )'''
Get all cards of a specific type (rarely used).
Return an array of cards, or an empty array if there is no cards of the specified type.
_ type: the type of cards
_ type_arg: if specified, return only cards with the specified "type_arg".
=== Shuffling ===
'''shuffle( $location )'''
Shuffle all cards in specific location.
Shuffle only works on locations where cards are on a "pile" (ex: "deck").
Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile.
97f690a53ba2e3134edbadeca0c00a07ceff10e2
651
650
2013-02-13T17:03:05Z
Sourisdudesert
1
/* Card standard format */
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
=== The 5 properties of each card ===
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card.
* '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?).
* '''location''' and '''location_arg''': These two values defines where is the card at now.
id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.
'''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
'''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
'''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer.
You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:
* 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
* 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
* 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").
Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.
=== Create a new Deck component ===
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method.
"Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts":
<pre>
// Create cards
$cards = array();
foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club
{
for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A
{
$cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1);
}
}
$this->cards->createCards( $cards, 'deck' );
</pre>
As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument).
Now, you are ready to use "Deck"!
=== Simple examples using Deck ===
(Most examples are from "Hearts" game)
<pre>
// In "getAllDatas', we need to send to the current player all the cards he has in hand:
$result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id );
</pre>
<pre>
// At some time we want to check if all the cards (52) are in player's hands:
if( $this->cards->countCardInLocation( 'hand' ) == 52 )
// do something
</pre>
<pre>
// When a player plays a card in front of him on the table:
$this->cards->moveCard( $card_id, 'cardsontable', $player_id );
// Note the use of the custom location 'cardsontable' here to keep track of cards on the table.
</pre>
<pre>
// This is a new hand: let's gather all cards from everywhere in the deck:
$this->cards->moveAllCardsInLocation( null, "deck" );
// And then shuffle the deck
$this->cards->shuffle( 'deck' );
// And then deal 13 cards to each player
// Deal 13 cards to each players
// Create deck, shuffle it and give 13 initial cards
$players = self::loadPlayersBasicInfos();
foreach( $players as $player_id => $player )
{
$cards = $this->cards->pickCards( 13, 'deck', $player_id );
// Notify player about his cards
self::notifyPlayer( $player_id, 'newHand', '', array(
'cards' => $cards
) );
}
// Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;)
</pre>
== Deck component reference ==
=== Initializing Deck component ===
'''init( $table_name )'''
Initialize the Deck component.
Argument:
* table_name: name of the DB table used by this Deck component.
Must be called before any other Deck method.
Usually, init is called in your game constructor.
Example with Hearts:
<pre>
function Hearts( )
{
(...)
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
}
</pre>
'''createCards( $cards, $location='deck', $location_arg=null )'''
Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game.
"cards" describe all cards that need to be created. "cards" is an array with the following format:
<pre>
// Create 1 card of type "1" with type_arg=99,
// and 4 cards of type "2" with type_arg=12,
// and 2 cards of type "3" with type_arg=33
$cards = array(
array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ),
array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ),
array( 'type' => 3, 'type_arg' => 33, nbr' => 2 )
...
);
</pre>
Note: During the "createCards" process, Deck generate unique IDs for all card items.
Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one.
If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location.
=== Card standard format ===
When Deck component methods are returning one or several cards, the following format is used:
<pre>
array(
'id' => .., // the card ID
'type' => .., // the card type
'type_arg' => .., // the card type argument
'location' => .., // the card location
'location_arg' => .. // the card location argument
);
</pre>
=== Picking cards ===
'''pickCard( $location, $player_id )'''
Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player.
Return the card picked or "null" if there are no more card in given location.
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCards( $nbr, $location, $player_id )'''
Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player.
Return an array with the cards picked, or "null" if there are no more card in given location.
Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location.
This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked.
'''pickCardForLocation( $from_location, $to_location, $location_arg=0 )'''
This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location.
_ from_location is the "pile" style location from where you are picking a card.
_ to_location is the location where you will place the card picked.
_ if "location_arg" is specified, the card picked will be set with this "location_arg".
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )'''
This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location.
_ from_location is the "pile" style location from where you are picking some cards.
_ to_location is the location where you will place the cards picked.
_ if "location_arg" is specified, the cards picked will be set with this "location_arg".
_ if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call.
This method supports auto-reshuffle (see "auto-reshuffle" below).
=== Moving cards ===
'''moveCard( $card_id, $location, $location_arg=0 )'''
Move the specific card to given location.
_ card_id: ID of the card to move.
_ location: location where to move the card.
_ location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0.
'''moveCards( $cards, $location, $location_arg )'''
Move the specific cards to given location.
_ cards: an array of IDs of cards to move.
_ location: location where to move the cards.
_ location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0.
'''insertCard( $card_id, $location, $location_arg )'''
Move a card to a specific "pile" location where card are ordered.
If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location.
(note: insertCardOnExtremePosition method below is more useful in most of the case)
'''insertCardOnExtremePosition( $card_id, $location, $bOnTop )'''
Move a card on top or at bottom of given "pile" type location.
'''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )'''
Move all cards in specified "from" location to given location.
_ from_location: where to take the cards
_ to_location: where to put the cards
_ from_location (optional): if specified, only cards with given "location_arg" are moved.
_ to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero.
Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below.
'''moveAllCardsInLocationKeepOrder( $from_location, $to_location )'''
Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards.
'''playCard( $card_id )'''
Move specified card at the top of the "discard" location.
Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true )
=== Get cards informations ===
'''getCard( $card_id )'''
Get specific card information.
Return null if this card is not found.
'''getCards( $cards_array )'''
Get specific cards information.
cards_array is an array of cards ID.
If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception.
'''getCardsInLocation( $location, $location_arg = null, $order_by = null )'''
Get all cards in specific location, as an array. Return an empty array if the location is empty.
_ location (string): the location where to get the cards.
_ location_arg (optional): if specified, return only cards with the specified "location_arg".
_ order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type".
'''countCardInLocation( $location, $location_arg=null )'''
Return the number of cards in specified location.
_ location (string): the location where to count the cards.
_ location_arg (optional): if specified, count only cards with the specified "location_arg".
'''countCardsInLocations()'''
Return the number of cards in each location of the game.
The method returns an associative array with the format "location" => "number of cards".
Example:
<pre>
array(
'deck' => 12,
'hand' => 21,
'discard' => 54,
'ontable' => 3
);
</pre>
'''countCardsByLocationArgs( $location )'''
Return the number of cards in each "location_arg" for the given location.
The method returns an associative array with the format "location_arg" => "number of cards".
Example: count the number of cards in each player's hand:
<pre>
countCardsByLocationArgs( 'hand' );
// Result:
array(
122345 => 5, // player 122345 has 5 cards in hand
123456 => 4 // and player 123456 has 4 cards in hand
);
</pre>
'''getPlayerHand( $player_id )'''
Get all cards in given player hand.
Note: This is an alias for:
getCardsInLocation( "hand", $player_id )
'''getCardOnTop( $location )'''
Get the card on top of the given ("pile" style) location, or null if the location is empty.
Note that the card pile won't be "auto-reshuffled" if there is no more card available.
'''getCardsOnTop( $nbr, $location )'''
Get the "$nbr" cards on top of the given ("pile" style) location.
The method return an array with at most "$nbr" elements (or a void array if there is no card in this location).
Note that the card pile won't be "auto-reshuffled" if there is not enough cards available.
'''getExtremePosition( $bGetMax ,$location )'''
(rarely used)
Get the position of cards at the top of the given location / at the bottom of the given location.
Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location).
If bGetMax=true, return the location of the top card of the pile.
If bGetMax=false, return the location of the bottom card of the pile.
'''getCardsOfType( $type, $type_arg=null )'''
Get all cards of a specific type (rarely used).
Return an array of cards, or an empty array if there is no cards of the specified type.
_ type: the type of cards
_ type_arg: if specified, return only cards with the specified "type_arg".
=== Shuffling ===
'''shuffle( $location )'''
Shuffle all cards in specific location.
Shuffle only works on locations where cards are on a "pile" (ex: "deck").
Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile.
30cc7f35ff1f13c94e1d1122b1dafc9e8a0dd77c
Main game logic: yourgamename.game.php
0
86
642
590
2013-02-12T11:54:45Z
Sourisdudesert
1
/* Notify players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
435c6857bd4d2b9828f2721bd88716e2c3c77355
Gamehelptroyes
0
26
645
54
2013-02-13T16:04:43Z
Peach
2372
/* Ziel */
wikitext
text/x-wiki
== Ziel ==
Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels.
== Rules summary ==
(This rules summary is based on the game help written by [http://boardgamegeek.com/user/pregremlin Andrew Agard] for Board Game Geek, under Creative Commons license. Please see [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] here for details. Thank you Andrew !)
===Initial Placement===
* In clockwise order place a citizen in empty space of one building
* Continue in counter clockwise order from last player and so on until all citizens placed
===Game play===
====Phase 0: Reveal the Activity cards====
Reveal activity card for each color corresponding to current round (first 3 rounds only)
====Phase 1: Income and salaries====
Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP
====Phase 2: Assembling the workforce====
Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district
====Phase 3: Events====
Reveal top red and white or yellow Event and place to right of queue (unlimited Events)
Events take effect from left to right
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Actions====
See below.
====Phase 5: End of the round====
Receive deniers from district
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Pass start player card left.
===Actions===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Activate Activity Card====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Combat Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Place a citizen on building====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Use Agriculture====
* Gain number of deniers equal to total value divided by 2 (round down)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
cac908b237e45cd5a4647769f0b295e42d37c72e
646
645
2013-02-13T16:26:08Z
Peach
2372
/* Regel Zusammenfassung */
wikitext
text/x-wiki
== Ziel ==
Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels.
== Regel Zusammenfassung ==
(Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !)
===Initial Placement===
* In clockwise order place a citizen in empty space of one building
* Continue in counter clockwise order from last player and so on until all citizens placed
===Spielablauf===
====Phase 0: Reveal the Activity cards====
Reveal activity card for each color corresponding to current round (first 3 rounds only)
====Phase 1: Income and salaries====
Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP
====Phase 2: Assembling the workforce====
Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district
====Phase 3: Events====
Reveal top red and white or yellow Event and place to right of queue (unlimited Events)
Events take effect from left to right
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Actions====
See below.
====Phase 5: End of the round====
Receive deniers from district
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Pass start player card left.
===Actions===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Activate Activity Card====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Combat Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Place a citizen on building====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Use Agriculture====
* Gain number of deniers equal to total value divided by 2 (round down)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
4d30bca9173f8e0b9cb90e627c422ac5c3a4acf3
647
646
2013-02-13T16:30:11Z
Peach
2372
/* Anfangs Aufstellung */
wikitext
text/x-wiki
== Ziel ==
Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels.
== Regel Zusammenfassung ==
(Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !)
===Anfangs Aufstellung===
* Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt
* Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind
===Spielablauf===
====Phase 0: Reveal the Activity cards====
Reveal activity card for each color corresponding to current round (first 3 rounds only)
====Phase 1: Income and salaries====
Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP
====Phase 2: Assembling the workforce====
Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district
====Phase 3: Events====
Reveal top red and white or yellow Event and place to right of queue (unlimited Events)
Events take effect from left to right
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Actions====
See below.
====Phase 5: End of the round====
Receive deniers from district
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Pass start player card left.
===Actions===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Activate Activity Card====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Combat Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Place a citizen on building====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Use Agriculture====
* Gain number of deniers equal to total value divided by 2 (round down)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
364bbde528d234afd19137233e2b874bc0e74508
648
647
2013-02-13T16:41:16Z
Peach
2372
/* Spielablauf */
wikitext
text/x-wiki
== Ziel ==
Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels.
== Regel Zusammenfassung ==
(Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !)
===Anfangs Aufstellung===
* Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt
* Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind
===Spielablauf===
====Phase 0: Aktionskarten aufdecken====
Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden)
====Phase 1: Einkommen und Lohn====
Erhalte 10 Deniers und zahle 1 für jeden Bishopric und 2 für jeden Bewohner im Palast oder verliere 2 Siegespunkte
====Phase 2: Aufbau der arbeiterschaft====
Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk
====Phase 3: Events====
Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events)
Events nehmen Einfluss von links nach rechts
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Aktionen====
Siehe unten.
====Phase 5: Ende der Runde====
Nehme Deniers aus deinem Bezirk
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Gib die Startspieler-Karte nach links
===Actions===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Activate Activity Card====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Combat Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Place a citizen on building====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Use Agriculture====
* Gain number of deniers equal to total value divided by 2 (round down)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
279f92427ac97dc8d2cf90cb1cb2f33c04c41c42
649
648
2013-02-13T16:43:36Z
Peach
2372
/* Aktionen
wikitext
text/x-wiki
== Ziel ==
Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels.
== Regel Zusammenfassung ==
(Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !)
===Anfangs Aufstellung===
* Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt
* Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind
===Spielablauf===
====Phase 0: Aktionskarten aufdecken====
Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden)
====Phase 1: Einkommen und Lohn====
Erhalte 10 Deniers und zahle 1 für jeden Bishopric und 2 für jeden Bewohner im Palast oder verliere 2 Siegespunkte
====Phase 2: Aufbau der arbeiterschaft====
Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk
====Phase 3: Events====
Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events)
Events nehmen Einfluss von links nach rechts
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Aktionen====
Siehe unten.
====Phase 5: Ende der Runde====
Nehme Deniers aus deinem Bezirk
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Gib die Startspieler-Karte nach links
===Aktionen===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Aktionskarten aktivieren====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Kampf Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Platzieren einen Bewohner in einem Gebäude====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Benutze Landwirtschaft====
* Erhalte eine Anzahl an Deniers gleich der Summe der Würfel durch 2 (abgerundet)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
a98c831f0b41c9f17c1b958e8162765515b1e1ce
Deck
0
101
652
651
2013-02-13T17:03:29Z
Sourisdudesert
1
/* Picking cards */
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
=== The 5 properties of each card ===
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card.
* '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?).
* '''location''' and '''location_arg''': These two values defines where is the card at now.
id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.
'''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
'''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
'''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer.
You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:
* 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
* 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
* 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").
Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.
=== Create a new Deck component ===
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method.
"Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts":
<pre>
// Create cards
$cards = array();
foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club
{
for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A
{
$cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1);
}
}
$this->cards->createCards( $cards, 'deck' );
</pre>
As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument).
Now, you are ready to use "Deck"!
=== Simple examples using Deck ===
(Most examples are from "Hearts" game)
<pre>
// In "getAllDatas', we need to send to the current player all the cards he has in hand:
$result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id );
</pre>
<pre>
// At some time we want to check if all the cards (52) are in player's hands:
if( $this->cards->countCardInLocation( 'hand' ) == 52 )
// do something
</pre>
<pre>
// When a player plays a card in front of him on the table:
$this->cards->moveCard( $card_id, 'cardsontable', $player_id );
// Note the use of the custom location 'cardsontable' here to keep track of cards on the table.
</pre>
<pre>
// This is a new hand: let's gather all cards from everywhere in the deck:
$this->cards->moveAllCardsInLocation( null, "deck" );
// And then shuffle the deck
$this->cards->shuffle( 'deck' );
// And then deal 13 cards to each player
// Deal 13 cards to each players
// Create deck, shuffle it and give 13 initial cards
$players = self::loadPlayersBasicInfos();
foreach( $players as $player_id => $player )
{
$cards = $this->cards->pickCards( 13, 'deck', $player_id );
// Notify player about his cards
self::notifyPlayer( $player_id, 'newHand', '', array(
'cards' => $cards
) );
}
// Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;)
</pre>
== Deck component reference ==
=== Initializing Deck component ===
'''init( $table_name )'''
Initialize the Deck component.
Argument:
* table_name: name of the DB table used by this Deck component.
Must be called before any other Deck method.
Usually, init is called in your game constructor.
Example with Hearts:
<pre>
function Hearts( )
{
(...)
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
}
</pre>
'''createCards( $cards, $location='deck', $location_arg=null )'''
Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game.
"cards" describe all cards that need to be created. "cards" is an array with the following format:
<pre>
// Create 1 card of type "1" with type_arg=99,
// and 4 cards of type "2" with type_arg=12,
// and 2 cards of type "3" with type_arg=33
$cards = array(
array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ),
array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ),
array( 'type' => 3, 'type_arg' => 33, nbr' => 2 )
...
);
</pre>
Note: During the "createCards" process, Deck generate unique IDs for all card items.
Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one.
If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location.
=== Card standard format ===
When Deck component methods are returning one or several cards, the following format is used:
<pre>
array(
'id' => .., // the card ID
'type' => .., // the card type
'type_arg' => .., // the card type argument
'location' => .., // the card location
'location_arg' => .. // the card location argument
);
</pre>
=== Picking cards ===
'''pickCard( $location, $player_id )'''
Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player.
Return the card picked or "null" if there are no more card in given location.
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCards( $nbr, $location, $player_id )'''
Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player.
Return an array with the cards picked, or "null" if there are no more card in given location.
Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location.
This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked.
'''pickCardForLocation( $from_location, $to_location, $location_arg=0 )'''
This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location.
* from_location is the "pile" style location from where you are picking a card.
* to_location is the location where you will place the card picked.
* if "location_arg" is specified, the card picked will be set with this "location_arg".
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )'''
This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location.
* from_location is the "pile" style location from where you are picking some cards.
* to_location is the location where you will place the cards picked.
* if "location_arg" is specified, the cards picked will be set with this "location_arg".
* if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call.
This method supports auto-reshuffle (see "auto-reshuffle" below).
=== Moving cards ===
'''moveCard( $card_id, $location, $location_arg=0 )'''
Move the specific card to given location.
_ card_id: ID of the card to move.
_ location: location where to move the card.
_ location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0.
'''moveCards( $cards, $location, $location_arg )'''
Move the specific cards to given location.
_ cards: an array of IDs of cards to move.
_ location: location where to move the cards.
_ location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0.
'''insertCard( $card_id, $location, $location_arg )'''
Move a card to a specific "pile" location where card are ordered.
If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location.
(note: insertCardOnExtremePosition method below is more useful in most of the case)
'''insertCardOnExtremePosition( $card_id, $location, $bOnTop )'''
Move a card on top or at bottom of given "pile" type location.
'''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )'''
Move all cards in specified "from" location to given location.
_ from_location: where to take the cards
_ to_location: where to put the cards
_ from_location (optional): if specified, only cards with given "location_arg" are moved.
_ to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero.
Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below.
'''moveAllCardsInLocationKeepOrder( $from_location, $to_location )'''
Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards.
'''playCard( $card_id )'''
Move specified card at the top of the "discard" location.
Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true )
=== Get cards informations ===
'''getCard( $card_id )'''
Get specific card information.
Return null if this card is not found.
'''getCards( $cards_array )'''
Get specific cards information.
cards_array is an array of cards ID.
If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception.
'''getCardsInLocation( $location, $location_arg = null, $order_by = null )'''
Get all cards in specific location, as an array. Return an empty array if the location is empty.
_ location (string): the location where to get the cards.
_ location_arg (optional): if specified, return only cards with the specified "location_arg".
_ order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type".
'''countCardInLocation( $location, $location_arg=null )'''
Return the number of cards in specified location.
_ location (string): the location where to count the cards.
_ location_arg (optional): if specified, count only cards with the specified "location_arg".
'''countCardsInLocations()'''
Return the number of cards in each location of the game.
The method returns an associative array with the format "location" => "number of cards".
Example:
<pre>
array(
'deck' => 12,
'hand' => 21,
'discard' => 54,
'ontable' => 3
);
</pre>
'''countCardsByLocationArgs( $location )'''
Return the number of cards in each "location_arg" for the given location.
The method returns an associative array with the format "location_arg" => "number of cards".
Example: count the number of cards in each player's hand:
<pre>
countCardsByLocationArgs( 'hand' );
// Result:
array(
122345 => 5, // player 122345 has 5 cards in hand
123456 => 4 // and player 123456 has 4 cards in hand
);
</pre>
'''getPlayerHand( $player_id )'''
Get all cards in given player hand.
Note: This is an alias for:
getCardsInLocation( "hand", $player_id )
'''getCardOnTop( $location )'''
Get the card on top of the given ("pile" style) location, or null if the location is empty.
Note that the card pile won't be "auto-reshuffled" if there is no more card available.
'''getCardsOnTop( $nbr, $location )'''
Get the "$nbr" cards on top of the given ("pile" style) location.
The method return an array with at most "$nbr" elements (or a void array if there is no card in this location).
Note that the card pile won't be "auto-reshuffled" if there is not enough cards available.
'''getExtremePosition( $bGetMax ,$location )'''
(rarely used)
Get the position of cards at the top of the given location / at the bottom of the given location.
Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location).
If bGetMax=true, return the location of the top card of the pile.
If bGetMax=false, return the location of the bottom card of the pile.
'''getCardsOfType( $type, $type_arg=null )'''
Get all cards of a specific type (rarely used).
Return an array of cards, or an empty array if there is no cards of the specified type.
_ type: the type of cards
_ type_arg: if specified, return only cards with the specified "type_arg".
=== Shuffling ===
'''shuffle( $location )'''
Shuffle all cards in specific location.
Shuffle only works on locations where cards are on a "pile" (ex: "deck").
Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile.
a290d4ecd4c4c4fee059d59ff4808671f7971637
653
652
2013-02-13T17:03:50Z
Sourisdudesert
1
/* Moving cards */
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
=== The 5 properties of each card ===
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card.
* '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?).
* '''location''' and '''location_arg''': These two values defines where is the card at now.
id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.
'''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
'''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
'''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer.
You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:
* 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
* 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
* 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").
Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.
=== Create a new Deck component ===
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method.
"Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts":
<pre>
// Create cards
$cards = array();
foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club
{
for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A
{
$cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1);
}
}
$this->cards->createCards( $cards, 'deck' );
</pre>
As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument).
Now, you are ready to use "Deck"!
=== Simple examples using Deck ===
(Most examples are from "Hearts" game)
<pre>
// In "getAllDatas', we need to send to the current player all the cards he has in hand:
$result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id );
</pre>
<pre>
// At some time we want to check if all the cards (52) are in player's hands:
if( $this->cards->countCardInLocation( 'hand' ) == 52 )
// do something
</pre>
<pre>
// When a player plays a card in front of him on the table:
$this->cards->moveCard( $card_id, 'cardsontable', $player_id );
// Note the use of the custom location 'cardsontable' here to keep track of cards on the table.
</pre>
<pre>
// This is a new hand: let's gather all cards from everywhere in the deck:
$this->cards->moveAllCardsInLocation( null, "deck" );
// And then shuffle the deck
$this->cards->shuffle( 'deck' );
// And then deal 13 cards to each player
// Deal 13 cards to each players
// Create deck, shuffle it and give 13 initial cards
$players = self::loadPlayersBasicInfos();
foreach( $players as $player_id => $player )
{
$cards = $this->cards->pickCards( 13, 'deck', $player_id );
// Notify player about his cards
self::notifyPlayer( $player_id, 'newHand', '', array(
'cards' => $cards
) );
}
// Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;)
</pre>
== Deck component reference ==
=== Initializing Deck component ===
'''init( $table_name )'''
Initialize the Deck component.
Argument:
* table_name: name of the DB table used by this Deck component.
Must be called before any other Deck method.
Usually, init is called in your game constructor.
Example with Hearts:
<pre>
function Hearts( )
{
(...)
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
}
</pre>
'''createCards( $cards, $location='deck', $location_arg=null )'''
Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game.
"cards" describe all cards that need to be created. "cards" is an array with the following format:
<pre>
// Create 1 card of type "1" with type_arg=99,
// and 4 cards of type "2" with type_arg=12,
// and 2 cards of type "3" with type_arg=33
$cards = array(
array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ),
array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ),
array( 'type' => 3, 'type_arg' => 33, nbr' => 2 )
...
);
</pre>
Note: During the "createCards" process, Deck generate unique IDs for all card items.
Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one.
If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location.
=== Card standard format ===
When Deck component methods are returning one or several cards, the following format is used:
<pre>
array(
'id' => .., // the card ID
'type' => .., // the card type
'type_arg' => .., // the card type argument
'location' => .., // the card location
'location_arg' => .. // the card location argument
);
</pre>
=== Picking cards ===
'''pickCard( $location, $player_id )'''
Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player.
Return the card picked or "null" if there are no more card in given location.
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCards( $nbr, $location, $player_id )'''
Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player.
Return an array with the cards picked, or "null" if there are no more card in given location.
Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location.
This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked.
'''pickCardForLocation( $from_location, $to_location, $location_arg=0 )'''
This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location.
* from_location is the "pile" style location from where you are picking a card.
* to_location is the location where you will place the card picked.
* if "location_arg" is specified, the card picked will be set with this "location_arg".
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )'''
This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location.
* from_location is the "pile" style location from where you are picking some cards.
* to_location is the location where you will place the cards picked.
* if "location_arg" is specified, the cards picked will be set with this "location_arg".
* if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call.
This method supports auto-reshuffle (see "auto-reshuffle" below).
=== Moving cards ===
'''moveCard( $card_id, $location, $location_arg=0 )'''
Move the specific card to given location.
* card_id: ID of the card to move.
* location: location where to move the card.
* location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0.
'''moveCards( $cards, $location, $location_arg )'''
Move the specific cards to given location.
* cards: an array of IDs of cards to move.
* location: location where to move the cards.
* location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0.
'''insertCard( $card_id, $location, $location_arg )'''
Move a card to a specific "pile" location where card are ordered.
If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location.
(note: insertCardOnExtremePosition method below is more useful in most of the case)
'''insertCardOnExtremePosition( $card_id, $location, $bOnTop )'''
Move a card on top or at bottom of given "pile" type location.
'''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )'''
Move all cards in specified "from" location to given location.
* from_location: where to take the cards
* to_location: where to put the cards
* from_location (optional): if specified, only cards with given "location_arg" are moved.
* to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero.
Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below.
'''moveAllCardsInLocationKeepOrder( $from_location, $to_location )'''
Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards.
'''playCard( $card_id )'''
Move specified card at the top of the "discard" location.
Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true )
=== Get cards informations ===
'''getCard( $card_id )'''
Get specific card information.
Return null if this card is not found.
'''getCards( $cards_array )'''
Get specific cards information.
cards_array is an array of cards ID.
If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception.
'''getCardsInLocation( $location, $location_arg = null, $order_by = null )'''
Get all cards in specific location, as an array. Return an empty array if the location is empty.
_ location (string): the location where to get the cards.
_ location_arg (optional): if specified, return only cards with the specified "location_arg".
_ order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type".
'''countCardInLocation( $location, $location_arg=null )'''
Return the number of cards in specified location.
_ location (string): the location where to count the cards.
_ location_arg (optional): if specified, count only cards with the specified "location_arg".
'''countCardsInLocations()'''
Return the number of cards in each location of the game.
The method returns an associative array with the format "location" => "number of cards".
Example:
<pre>
array(
'deck' => 12,
'hand' => 21,
'discard' => 54,
'ontable' => 3
);
</pre>
'''countCardsByLocationArgs( $location )'''
Return the number of cards in each "location_arg" for the given location.
The method returns an associative array with the format "location_arg" => "number of cards".
Example: count the number of cards in each player's hand:
<pre>
countCardsByLocationArgs( 'hand' );
// Result:
array(
122345 => 5, // player 122345 has 5 cards in hand
123456 => 4 // and player 123456 has 4 cards in hand
);
</pre>
'''getPlayerHand( $player_id )'''
Get all cards in given player hand.
Note: This is an alias for:
getCardsInLocation( "hand", $player_id )
'''getCardOnTop( $location )'''
Get the card on top of the given ("pile" style) location, or null if the location is empty.
Note that the card pile won't be "auto-reshuffled" if there is no more card available.
'''getCardsOnTop( $nbr, $location )'''
Get the "$nbr" cards on top of the given ("pile" style) location.
The method return an array with at most "$nbr" elements (or a void array if there is no card in this location).
Note that the card pile won't be "auto-reshuffled" if there is not enough cards available.
'''getExtremePosition( $bGetMax ,$location )'''
(rarely used)
Get the position of cards at the top of the given location / at the bottom of the given location.
Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location).
If bGetMax=true, return the location of the top card of the pile.
If bGetMax=false, return the location of the bottom card of the pile.
'''getCardsOfType( $type, $type_arg=null )'''
Get all cards of a specific type (rarely used).
Return an array of cards, or an empty array if there is no cards of the specified type.
_ type: the type of cards
_ type_arg: if specified, return only cards with the specified "type_arg".
=== Shuffling ===
'''shuffle( $location )'''
Shuffle all cards in specific location.
Shuffle only works on locations where cards are on a "pile" (ex: "deck").
Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile.
f4a855fc2b2063c8daae2d2cf77bbaf3876e6401
654
653
2013-02-13T17:04:14Z
Sourisdudesert
1
/* Get cards informations */
wikitext
text/x-wiki
"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.
Using "deck", you will be able to use the following features without writing a single SQL database request:
* Place cards in pile, shuffle cards, draw cards one by one or many by many.
* "Auto-reshuffle" discard pile into deck when deck is empty.
* Move cards between different locations: hands of players, the table, ...
== Using Deck: Hearts example ==
Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.
== Deck overview ==
With Deck component, you manage all cards of your game.
=== The 5 properties of each card ===
Using Deck component, each card will have 5 properties:
* '''id''': This is the unique ID of each card.
* '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?).
* '''location''' and '''location_arg''': These two values defines where is the card at now.
id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.
'''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.
'''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.
Examples of usage of "type" and "type_arg":
* In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
* In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
* In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.
'''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer.
You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:
* 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
* 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
* 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").
Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.
=== Create a new Deck component ===
For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":
<pre>
CREATE TABLE IF NOT EXISTS `card` (
`card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`card_type` varchar(16) NOT NULL,
`card_type_arg` int(11) NOT NULL,
`card_location` varchar(16) NOT NULL,
`card_location_arg` int(11) NOT NULL,
PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:
<pre>
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
</pre>
Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).
Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method.
"Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts":
<pre>
// Create cards
$cards = array();
foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club
{
for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A
{
$cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1);
}
}
$this->cards->createCards( $cards, 'deck' );
</pre>
As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument).
Now, you are ready to use "Deck"!
=== Simple examples using Deck ===
(Most examples are from "Hearts" game)
<pre>
// In "getAllDatas', we need to send to the current player all the cards he has in hand:
$result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id );
</pre>
<pre>
// At some time we want to check if all the cards (52) are in player's hands:
if( $this->cards->countCardInLocation( 'hand' ) == 52 )
// do something
</pre>
<pre>
// When a player plays a card in front of him on the table:
$this->cards->moveCard( $card_id, 'cardsontable', $player_id );
// Note the use of the custom location 'cardsontable' here to keep track of cards on the table.
</pre>
<pre>
// This is a new hand: let's gather all cards from everywhere in the deck:
$this->cards->moveAllCardsInLocation( null, "deck" );
// And then shuffle the deck
$this->cards->shuffle( 'deck' );
// And then deal 13 cards to each player
// Deal 13 cards to each players
// Create deck, shuffle it and give 13 initial cards
$players = self::loadPlayersBasicInfos();
foreach( $players as $player_id => $player )
{
$cards = $this->cards->pickCards( 13, 'deck', $player_id );
// Notify player about his cards
self::notifyPlayer( $player_id, 'newHand', '', array(
'cards' => $cards
) );
}
// Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;)
</pre>
== Deck component reference ==
=== Initializing Deck component ===
'''init( $table_name )'''
Initialize the Deck component.
Argument:
* table_name: name of the DB table used by this Deck component.
Must be called before any other Deck method.
Usually, init is called in your game constructor.
Example with Hearts:
<pre>
function Hearts( )
{
(...)
$this->cards = self::getNew( "module.common.deck" );
$this->cards->init( "card" );
}
</pre>
'''createCards( $cards, $location='deck', $location_arg=null )'''
Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game.
"cards" describe all cards that need to be created. "cards" is an array with the following format:
<pre>
// Create 1 card of type "1" with type_arg=99,
// and 4 cards of type "2" with type_arg=12,
// and 2 cards of type "3" with type_arg=33
$cards = array(
array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ),
array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ),
array( 'type' => 3, 'type_arg' => 33, nbr' => 2 )
...
);
</pre>
Note: During the "createCards" process, Deck generate unique IDs for all card items.
Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one.
If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location.
=== Card standard format ===
When Deck component methods are returning one or several cards, the following format is used:
<pre>
array(
'id' => .., // the card ID
'type' => .., // the card type
'type_arg' => .., // the card type argument
'location' => .., // the card location
'location_arg' => .. // the card location argument
);
</pre>
=== Picking cards ===
'''pickCard( $location, $player_id )'''
Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player.
Return the card picked or "null" if there are no more card in given location.
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCards( $nbr, $location, $player_id )'''
Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player.
Return an array with the cards picked, or "null" if there are no more card in given location.
Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location.
This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked.
'''pickCardForLocation( $from_location, $to_location, $location_arg=0 )'''
This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location.
* from_location is the "pile" style location from where you are picking a card.
* to_location is the location where you will place the card picked.
* if "location_arg" is specified, the card picked will be set with this "location_arg".
This method supports auto-reshuffle (see "auto-reshuffle" below).
'''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )'''
This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location.
* from_location is the "pile" style location from where you are picking some cards.
* to_location is the location where you will place the cards picked.
* if "location_arg" is specified, the cards picked will be set with this "location_arg".
* if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call.
This method supports auto-reshuffle (see "auto-reshuffle" below).
=== Moving cards ===
'''moveCard( $card_id, $location, $location_arg=0 )'''
Move the specific card to given location.
* card_id: ID of the card to move.
* location: location where to move the card.
* location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0.
'''moveCards( $cards, $location, $location_arg )'''
Move the specific cards to given location.
* cards: an array of IDs of cards to move.
* location: location where to move the cards.
* location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0.
'''insertCard( $card_id, $location, $location_arg )'''
Move a card to a specific "pile" location where card are ordered.
If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location.
(note: insertCardOnExtremePosition method below is more useful in most of the case)
'''insertCardOnExtremePosition( $card_id, $location, $bOnTop )'''
Move a card on top or at bottom of given "pile" type location.
'''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )'''
Move all cards in specified "from" location to given location.
* from_location: where to take the cards
* to_location: where to put the cards
* from_location (optional): if specified, only cards with given "location_arg" are moved.
* to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero.
Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below.
'''moveAllCardsInLocationKeepOrder( $from_location, $to_location )'''
Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards.
'''playCard( $card_id )'''
Move specified card at the top of the "discard" location.
Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true )
=== Get cards informations ===
'''getCard( $card_id )'''
Get specific card information.
Return null if this card is not found.
'''getCards( $cards_array )'''
Get specific cards information.
cards_array is an array of cards ID.
If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception.
'''getCardsInLocation( $location, $location_arg = null, $order_by = null )'''
Get all cards in specific location, as an array. Return an empty array if the location is empty.
* location (string): the location where to get the cards.
* location_arg (optional): if specified, return only cards with the specified "location_arg".
* order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type".
'''countCardInLocation( $location, $location_arg=null )'''
Return the number of cards in specified location.
* location (string): the location where to count the cards.
* location_arg (optional): if specified, count only cards with the specified "location_arg".
'''countCardsInLocations()'''
Return the number of cards in each location of the game.
The method returns an associative array with the format "location" => "number of cards".
Example:
<pre>
array(
'deck' => 12,
'hand' => 21,
'discard' => 54,
'ontable' => 3
);
</pre>
'''countCardsByLocationArgs( $location )'''
Return the number of cards in each "location_arg" for the given location.
The method returns an associative array with the format "location_arg" => "number of cards".
Example: count the number of cards in each player's hand:
<pre>
countCardsByLocationArgs( 'hand' );
// Result:
array(
122345 => 5, // player 122345 has 5 cards in hand
123456 => 4 // and player 123456 has 4 cards in hand
);
</pre>
'''getPlayerHand( $player_id )'''
Get all cards in given player hand.
Note: This is an alias for:
getCardsInLocation( "hand", $player_id )
'''getCardOnTop( $location )'''
Get the card on top of the given ("pile" style) location, or null if the location is empty.
Note that the card pile won't be "auto-reshuffled" if there is no more card available.
'''getCardsOnTop( $nbr, $location )'''
Get the "$nbr" cards on top of the given ("pile" style) location.
The method return an array with at most "$nbr" elements (or a void array if there is no card in this location).
Note that the card pile won't be "auto-reshuffled" if there is not enough cards available.
'''getExtremePosition( $bGetMax ,$location )'''
(rarely used)
Get the position of cards at the top of the given location / at the bottom of the given location.
Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location).
If bGetMax=true, return the location of the top card of the pile.
If bGetMax=false, return the location of the bottom card of the pile.
'''getCardsOfType( $type, $type_arg=null )'''
Get all cards of a specific type (rarely used).
Return an array of cards, or an empty array if there is no cards of the specified type.
* type: the type of cards
* type_arg: if specified, return only cards with the specified "type_arg".
=== Shuffling ===
'''shuffle( $location )'''
Shuffle all cards in specific location.
Shuffle only works on locations where cards are on a "pile" (ex: "deck").
Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile.
888d00b0a38148f59e241b98b3bb921eba1403f2
Game interface logic: yourgamename.js
0
88
655
644
2013-02-13T17:07:00Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
=== Player's panel disabling/enabling
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
317bdc295b668f5ee01046885997fe77b6f0c0de
656
655
2013-02-13T17:07:21Z
Sourisdudesert
1
/* Update players score */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
6c6bae4526ba6f719fe08686230ab499d1dbbec7
657
656
2013-02-13T17:07:28Z
Sourisdudesert
1
/* Player's panel disabling/enabling */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Player's panel disabling/enabling ==
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
2af44a5cdab3cfff195bc95c9cf3b64104568a06
673
657
2013-03-06T14:47:17Z
Sourisdudesert
1
/* Players input */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Player's panel disabling/enabling ==
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
bd972f271ef42252114b8f4d86ef99ebfc8ad83f
674
673
2013-03-06T14:52:26Z
Sourisdudesert
1
/* Player's panel disabling/enabling */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Player's panel disabling/enabling ==
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
bbdd8317ec1cbd390a37b6e0dbe5659007b947ff
676
674
2013-03-06T15:02:01Z
Sourisdudesert
1
/* Player's panel disabling/enabling */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
bc879e9abee75c711f10c9937ff891393783156f
682
676
2013-03-06T15:18:06Z
Sourisdudesert
1
/* General tips */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( node, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( node, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
e1ea57068eed4a0c9bc22b8972fd0e776b21faee
Gamehelpcoloretto
0
33
658
192
2013-02-14T22:53:02Z
Peach
2372
wikitext
text/x-wiki
Während man im regulären Spiel entscheiden muss, welche Stapel positiv/negativ gewertet werden und wo man die Joker platziert, errechnet diese Version automatisch den höchst möglichen Score.
7f464fbdfa930182f9877ed6fef567378c23823a
Faq
0
3
659
100
2013-02-15T07:41:51Z
Larrygates
2403
/* What are the games available on BGA? */
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
437cf4ae7997f52afc3d4a93addca089139ad5f6
Practical debugging
0
100
660
632
2013-02-15T15:09:18Z
Een
3
/* Javascript does not know how to sum two numbers */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
As these functions are not consequences of a user action, there is no current player defined.
As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
=== when refreshing the web page, the interface remains on "Application loading..." ===
In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load.
To find this error, check if there is an error message in the Javascript console (F12).
If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition.
=== When I do a move, I got "Move recorded, waiting for update ..." forever ===
"Move recorded" means that your ajaxcall request has been sent to the server and returned normally.
"Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did.
If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code.
=== Some player action is triggered randomly when I click somewhere on the game area ===
You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area.
Most of the time it happens in this situation, when my_object element does not exists:
<pre>
dojo.connect( $("my_object"), "onclick", this, function() {
...
}
</pre>
To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not.
=== Javascript does not know how to sum two numbers ===
Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers.
As a result:
<pre>
var i=1;
i += notif.args.increment; // With notif.args.increment='1'
alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings !
</pre>
To solve this, you should use the "toint" function:
<pre>
var i=1;
i += toint( notif.args.increment ); // With notif.args.increment='1'
alert( i ); // i=2 :)
</pre>
=== Javascript: do not use substr with negative numbers ===
To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE:
<pre>
var three_last_characters = string.substr( -3 ); // Wrong
var three_last_characters = string.slice( -3 ); // Correct
</pre>
d86a3fa2d7ac9e139610b3420fc0d619ea9fc38a
Gamehelptroyes
0
26
661
649
2013-02-15T15:14:24Z
Pablo74
19
/* Phase 1: Einkommen und Lohn */
wikitext
text/x-wiki
== Ziel ==
Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels.
== Regel Zusammenfassung ==
(Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !)
===Anfangs Aufstellung===
* Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt
* Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind
===Spielablauf===
====Phase 0: Aktionskarten aufdecken====
Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden)
====Phase 1: Einkommen und Lohn====
Erhalte 10 Deniers und zahle 1 Denier für jeden deiner Bewohner im Bischofssitz und 2 Deniers für jeden deiner Bewohner im Palast oder verliere 2 Siegespunkte
====Phase 2: Aufbau der arbeiterschaft====
Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk
====Phase 3: Events====
Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events)
Events nehmen Einfluss von links nach rechts
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Aktionen====
Siehe unten.
====Phase 5: Ende der Runde====
Nehme Deniers aus deinem Bezirk
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Gib die Startspieler-Karte nach links
===Aktionen===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Aktionskarten aktivieren====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Kampf Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Platzieren einen Bewohner in einem Gebäude====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Benutze Landwirtschaft====
* Erhalte eine Anzahl an Deniers gleich der Summe der Würfel durch 2 (abgerundet)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
87a4c2e79c8cb54682718deadfb347051f4a4664
662
661
2013-02-15T15:15:46Z
Pablo74
19
/* Phase 5: Ende der Runde */
wikitext
text/x-wiki
== Ziel ==
Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels.
== Regel Zusammenfassung ==
(Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !)
===Anfangs Aufstellung===
* Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt
* Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind
===Spielablauf===
====Phase 0: Aktionskarten aufdecken====
Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden)
====Phase 1: Einkommen und Lohn====
Erhalte 10 Deniers und zahle 1 Denier für jeden deiner Bewohner im Bischofssitz und 2 Deniers für jeden deiner Bewohner im Palast oder verliere 2 Siegespunkte
====Phase 2: Aufbau der arbeiterschaft====
Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk
====Phase 3: Events====
Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events)
Events nehmen Einfluss von links nach rechts
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Aktionen====
Siehe unten.
====Phase 5: Ende der Runde====
Nimm Deniers aus deinem Bezirk
Nimm deine liegenden Bürger aus den Gebäuden in deinen persönlichen Vorrat
Unbenutze Würfel gehen zurück in den allgemeinen Vorrat
Gib die Startspieler-Karte nach links
===Aktionen===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Aktionskarten aktivieren====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Kampf Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Platzieren einen Bewohner in einem Gebäude====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Benutze Landwirtschaft====
* Erhalte eine Anzahl an Deniers gleich der Summe der Würfel durch 2 (abgerundet)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
e8990947207bb3915058a4f1087c7046155f59bd
665
662
2013-02-21T15:08:59Z
Peach
2372
/* Regel Zusammenfassung */
wikitext
text/x-wiki
== Ziel ==
Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels.
== Regel Zusammenfassung ==
(Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !)
===Anfangs Aufstellung===
* Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt
* Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind
===Spielablauf===
====Phase 0: Aktionskarten aufdecken====
Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden)
====Phase 1: Einkommen und Lohn====
Erhalte 10 Deniers und zahle 1 Denier für jeden deiner Bewohner im Bischofssitz und 2 Deniers für jeden deiner Bewohner im Palast oder verliere 2 Siegespunkte
====Phase 2: Aufbau der Arbeiterschaft====
Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk
====Phase 3: Events====
Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events)
Events nehmen Einfluss von links nach rechts
* Militär: Der Startspieler nimmt für jedes Würfelsymbol einen schwarzen Würfel
* Andere Events: siehe Anhang (Bekämpfung nicht möglich: bekämpfe so viel wie möglich und verliere 2 Siegpunkte)
Nach den Events, Rolle den schwarzen Würfel und kontere:
* Startspieler muss den höchsten Wert mit einem oder mehreren Würfeln aus seinem Bezirk kontern. Gesamtwert muss >= Würfel sein. Mehrere Würfel gleichzeitig kontern ist möglich
* Erhalte 1 Einflusspunkt für jeden gekonterten Würfel (kontern nicht möglich: entferne Würfel und verliere 2 Siegpunkte)
* Im Uhrzeigersinn müssen die Spieler den höchsten übrig geblieben kontern bis alle gekontert sind
* Benutze Würfel jeder Farbe. Rote Würfel werden verdoppelt. Würfel können nicht gekauft und Aktionen nicht ausgeübt werden.
====Phase 4: Aktionen====
Siehe unten.
====Phase 5: Ende der Runde====
Nimm Deniers aus deinem Bezirk
Nimm deine liegenden Bürger aus den Gebäuden in deinen persönlichen Vorrat
Unbenutze Würfel gehen zurück in den allgemeinen Vorrat
Gib die Startspieler-Karte nach links
===Aktionen===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Aktionskarten aktivieren====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Kampf Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Platzieren einen Bewohner in einem Gebäude====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Benutze Landwirtschaft====
* Erhalte eine Anzahl an Deniers gleich der Summe der Würfel durch 2 (abgerundet)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
10e7539cf69405e6f021f88b33134b76ab2668a6
Gamehelpquoridor
0
102
663
2013-02-19T00:19:11Z
Magicalvin
2439
Quoridor Request for Different Size Board
wikitext
text/x-wiki
Hi,is it possible to edit the Quoridor board to different size board? ie 15x15 and different number of fences? ie 20
acbb73649bc695ffaf83329331452d7bab6fff75
664
663
2013-02-20T03:50:12Z
Kaminix
2393
Page emptied (non-rule text)
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
666
664
2013-02-24T03:36:21Z
Airandfingers
2504
wikitext
text/x-wiki
Corridor is a 2-player game, the object of which is to move your pawn to the other side of a 9x9 board.
e5f5b0f70c54b52e359d958322b786afb0a71567
667
666
2013-02-28T09:23:03Z
Magicalvin
2439
wikitext
text/x-wiki
Corridor is a 2-player game, the object of which is to move your pawn to the other side of a 9x9 board before your opponent.
You can either move your man up,down or sideways or put a fence down. Players can jump over an opponent that he is next to or jump diagonally if he is next to a fence. Players cannot jump over fences. Players can put a fence down to block an opponent, but must allow at least one path to get to his winning side.
You have only 10 fences. There is a fence counter by your name. Set traps to delay the opponent and create corridors to a winning path. You can concede the game by clicking on the square by your name and clicking "Concede...". You must have completed 50% or more of your game.
There is an optional starting "Off the Center Aisle" Variation. Players agree to play this variation. The first player moves sideways and the second player move sideways in the opposite direction. The players keep on moving sideways until they agree to stop.
4adf60484c8ac4fea674576ec269f7e4d43c9364
695
667
2013-03-16T17:38:00Z
Sirius136
2706
wikitext
text/x-wiki
[http://heyjude0929.pixnet.net/blog/post/26923277-%5B%E9%81%8A%E6%88%B2%E4%BB%8B%E7%B4%B9%5D%E6%AD%A5%E6%AD%A5%E7%82%BA%E7%87%9Fquoridor]步步為營(zh)
Corridor is a 2-player game, the object of which is to move your pawn to the other side of a 9x9 board before your opponent.
You can either move your man up,down or sideways or put a fence down. Players can jump over an opponent that he is next to or jump diagonally if he is next to a fence. Players cannot jump over fences. Players can put a fence down to block an opponent, but must allow at least one path to get to his winning side.
You have only 10 fences. There is a fence counter by your name. Set traps to delay the opponent and create corridors to a winning path. You can concede the game by clicking on the square by your name and clicking "Concede...". You must have completed 50% or more of your game.
There is an optional starting "Off the Center Aisle" Variation. Players agree to play this variation. The first player moves sideways and the second player move sideways in the opposite direction. The players keep on moving sideways until they agree to stop.
81f6185c44e295d3d224159201b0b4d3a368fc64
토론:Gamehelphearts
1
103
668
2013-03-02T23:23:01Z
Chandler123
2569
Created page with "it seems to me that if you shoot the moon you should have the option to increase your own score or decrease the score of the other players"
wikitext
text/x-wiki
it seems to me that if you shoot the moon you should have the option to increase your own score or decrease the score of the other players
5cd6ca4386ce8f33f76e892c009dd7ccc85c583b
671
668
2013-03-05T04:16:20Z
Msome
2487
wikitext
text/x-wiki
chandler123: it seems to me that if you shoot the moon you should have the option to increase your own score or decrease the score of the other players.
msome: That is common practice in the real world, but would make the length of an online game harder to predict, a problem for some players. I'd like to see an in-between solution: shooting the moon decreases the score of other players, unless doing so would end the game with you not in 1st place... in which case it instead increases your score by 26. In any case this discussion should be in the Forum, as I doubt anyone is reaing this talk page :)
7c6db170d1f2268afb4880b703201159b31b1afa
Gamehelpseasons
0
43
669
185
2013-03-03T05:24:18Z
Thoradian
997
wikitext
text/x-wiki
Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
Star - increase the maximum card player can summon (max 15)
Elements - Gain an energy of the element shown (water, earth, air, fire)
Numbers - Gain the number of Crystals as indicated by the number
Square card - Draw a card
Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at)
Dots - Indicate how fast the marker progress through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
Card summon by other card but due to limitation of the star will cause the new card to be discarded, no refund.
5552e6fb806e97da9943bc61794ef1a78d500b88
Gamehelphearts
0
52
670
234
2013-03-05T04:08:41Z
Msome
2487
moon /slam etiquette
wikitext
text/x-wiki
Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack.
'''Rank'''
A (high) to 2 (low).
'''Setup'''
The entire deck is dealt, giving you a hand of 13 cards. After looking at your hand, choose three cards to pass to another player.
The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player across the table, (3rd hand) to the player on your right, (4th hand) no passing. The rotation repeats until the game ends.
'''Tricks'''
After passing cards, the player holding the 2 of clubs leads the first trick.
Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs.
The highest card of the suit led wins the trick. The winner of a trick starts the next trick.
Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.]
There is no trump suit.
'''Scoring'''
At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13.
If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as "shooting the moon", or "slam"), that player scores 0 and all other players score -26. Warning other players about an attempt to shoot the moon is team play, and a breach of Hearts etiquette.
When one or more players reach zero, the game ends. The player with the highest score wins.
'''Variants'''
Normal game is 100 points.
Quick game is 75 points.
30e89bee40751176339d12f280b2f8d9cb48a3ca
Gamehelptakenoko
0
104
672
2013-03-06T03:32:42Z
Terrycloth
2601
Created page with "The game appears to think that the plot objectives are oriented. Since the rules say nothing about this it might be a bug."
wikitext
text/x-wiki
The game appears to think that the plot objectives are oriented. Since the rules say nothing about this it might be a bug.
9008df23bbb966b1f34a0f89c9c6ade47840bd7a
696
672
2013-03-17T02:30:13Z
Jirikki
2655
wikitext
text/x-wiki
Quick Reference Guide
Each turn consists of 2 steps:
1) Determine weather
2) Perform 2 different actions and complete objectives
Weather Types (always optional)
Sun - take a 3rd action
Rain - grow 1 bamboo on any irrigated plot
Wind - take two identical actions
Storm - move panda to any plot and he eats a bamboo as normal
Clouds - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather for this turn
Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed.
Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo.
Plots can only be placed adjacent to the pond or where it is next to 2 other plots in play.
The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color.
Game ends when a certain number of objectives have been completed.
2 players - 9 objectives
3 players - 8 objectives
4 players - 7 objectives
The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn.
The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win.
fa07912e1a73702b1075cc1d4d35db8b91949a7d
697
696
2013-03-17T02:33:50Z
Jirikki
2655
wikitext
text/x-wiki
Quick Reference Guide
Each turn consists of 2 steps:
1) Determine weather
2) Perform 2 different actions and complete objectives
Weather Types (always optional)
Sun - take a 3rd action
Rain - grow 1 bamboo on any irrigated plot
Wind - take two identical actions
Storm - move panda to any plot and he eats a bamboo as normal
Clouds - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather for this turn
Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed.
Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo.
Plots can only be placed adjacent to the pond or where it is next to 2 other plots in play.
The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color.
Game ends when a certain number of objectives have been completed.
2 players - 9 objectives
3 players - 8 objectives
4 players - 7 objectives
The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn.
The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win.
2b1801a348c4d02de75d3218816726ed3f00ca4a
Translations
0
94
675
606
2013-03-06T14:56:14Z
Sourisdudesert
1
/* How to not make translators crazy ;) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== How to not make translators crazy ;) ==
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
<pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre>
Write instead:
<pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre>
(or the equivalent "dojo.string.substitute" in Javascript)
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings.
* The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate.
* Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY".
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
Note: what is also possible to do is
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
b93a5f713e0a56d8e521c6d6cc54a2520dffbb0f
Stock
0
97
677
643
2013-03-06T15:05:36Z
Sourisdudesert
1
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
_ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
_ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
_ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
_ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''1st case'''
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''2nd case'''
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''3rd case'''
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
924af9cf8ebeed02fd579a8fa62baf6ca78c34f6
678
677
2013-03-06T15:06:03Z
Sourisdudesert
1
/* Tips when adding/removing items to/from Stock components */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
_ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
_ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
_ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
_ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
46fa0666b198c0c2ba93d6edcb88858e35fb57a7
699
678
2013-03-20T16:59:00Z
Sourisdudesert
1
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
_ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
_ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
_ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
_ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
a38bf1471a7860fdd10e302c07b6b1770bb18825
700
699
2013-03-20T16:59:47Z
Sourisdudesert
1
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
_ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
c61aed62adbb829cc6421e4d740a4d9eab88e1f5
701
700
2013-03-20T17:00:01Z
Sourisdudesert
1
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
b31bae02a5f0ea27a4deff6893d5d96574136897
Main game logic: yourgamename.game.php
0
86
679
642
2013-03-06T15:09:36Z
Sourisdudesert
1
/* Game states and active players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
53093afae2c0bf7fb0a989679b2b7f3977453591
680
679
2013-03-06T15:09:55Z
Sourisdudesert
1
/* Game states and active players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
5f3667a959afcc309f1ac96079dcb6fa777af169
686
680
2013-03-06T15:32:43Z
Sourisdudesert
1
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
7406f722579bbd5bcf3e69a11feb4e5ac8df0a76
687
686
2013-03-06T15:35:02Z
Sourisdudesert
1
/* Zombie mode */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new feException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
8897bcce501f79e77cb6106fb3652f3879e79803
688
687
2013-03-06T15:35:34Z
Sourisdudesert
1
/* Zombie mode */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new feException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
1bbaf94790e736345d32cf42d40095e027660046
Game interface stylesheet: yourgamename.css
0
96
681
634
2013-03-06T15:17:28Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the CSS stylesheet of your game User Interface.
Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript.
Usually, you are using CSS to:
1°) define the overall layout of your game
(ex: place the board on the top left, place player's hand beside, place the deck on the right, ...).
2°) create your CSS-sprites:
All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly.
Example:
<pre>
Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image):
.white_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: 0px 0px;
}
.black_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: -20px 0px;
}
.token {
width: 20px;
height: 20px;
background-repeat: none;
}
</pre>
3°) ... anything else:
It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query).
This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily.
Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary.
Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them.
== spectatorMode ==
fd49cb098fa0e7edace88c6cc5445536ca0527ec
683
681
2013-03-06T15:20:58Z
Sourisdudesert
1
/* spectatorMode */
wikitext
text/x-wiki
This is the CSS stylesheet of your game User Interface.
Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript.
Usually, you are using CSS to:
1°) define the overall layout of your game
(ex: place the board on the top left, place player's hand beside, place the deck on the right, ...).
2°) create your CSS-sprites:
All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly.
Example:
<pre>
Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image):
.white_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: 0px 0px;
}
.black_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: -20px 0px;
}
.token {
width: 20px;
height: 20px;
background-repeat: none;
}
</pre>
3°) ... anything else:
It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query).
This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily.
Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary.
Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them.
== spectatorMode ==
When a spectator (= a player that is not part of the game) is viewing a game, the BGA framework add the CSS class "spectatorMode" to the wrapping HTML tag of your game.
This way, if you want to apply a special style to some elements of your game for spectators, you can do this in your CSS:
<pre>
.spectatorMode #your_element_id {
/* your special style */
}
</pre>
The most common usage of this is to hide some elements to spectators. For example, to hide "my hand" elements:
<pre>
.spectatorMode #my_hand {
display: none;
}
</pre>
88bad6d7e34c7c8a69b27e76a3f8b8949b28656d
Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl
0
98
684
602
2013-03-06T15:23:33Z
Sourisdudesert
1
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "hearts_hearts.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
Using "blocks", you can repeat a piece of HTML from your template several time.
You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares:
<pre>
(in reversi_reversi.tpl)
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
<div id="discs">
</div>
</div>
(in reversi.view.php)
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Explanations:
* You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square".
* In your view, you declare your block using "begin_block" method.
* Then, you can insert as many block as you want to, using "insert_block" method.
The insert_block method takes 2 parameters:
* the name of the block to insert.
* an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP).
== Nested blocks ==
You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it:
<pre>
(In template file)
<!-- BEGIN player -->
<div class="miniboard" id="miniboard_{PLAYER_ID}">
<div class="card_places">
<!-- BEGIN card_place -->
<div id="card_place_{PLAYER_ID}_{PLACE_ID}">
</div>
<!-- END card_place -->
</div>
</div>
<!-- END player -->
(In view file)
$this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first
$this->page->begin_block( "mygame_mygame.tpl", "player" );
foreach( $players as $player_id => $player )
{
// Important: nested block must be reset here, otherwise the second player miniboard will
// have 8 card_place, the third will have 12 card_place, and so one...
$this->page->reset_subblocks( 'card_place' );
for( $i=1; $i<=4; $i++ )
{
$this->page->insert_block( "card_place", array(
'PLAYER_ID' => $player_id,
'PLACE_ID' => $i
);
}
$this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id );
}
</pre>
== Javascript templates ==
For game elements that come and go from the game area, we suggest you to define a Javascript template.
A Javascript template is defined in your template file like this:
(Reversi Token from Reversi example):
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: a section for javascript templates is already available at the end of your template skeleton file.
Then, you can use this javascript template to insert this piece of HTML in your game interface, like this:
<pre>
dojo.place( this.format_block( 'jstpl_disc', {
xy: x+''+y,
color: color
} ) , 'discs' );
</pre>
== How to access game information from .view.php? ==
From your .view.php, you can access the following:
=== Access current player id===
<pre>
global $g_user;
$current_player_id = $g_user->get_id();
</pre>
=== Access game object ===
In your view file, "$this->game" contains an instance of your main game class.
Example:
<pre>
// Access to some game elements description described in your "material.inc.php":
$my_cards_types = $this->game->card_types;
// Access to any (public) method defined in my .game.php file:
$result = $this->game->myMethod();
</pre>
== Tips: display a nice button ==
From time to time, you need to display a standard button in your interface. BGA framework provides you a standard button that you can use directly in your interface:
<pre>
<a href="#" id="my_button_id" class="button"><span>My button label</span></a>
</pre>
Note: To see it in action, check for example a Coloretto game
dfd849b48a11ad56d4e38edef008e0e22a155b02
685
684
2013-03-06T15:23:43Z
Sourisdudesert
1
/* Tips: display a nice button */
wikitext
text/x-wiki
These 2 files work together to provide the HTML layout of your game.
Using these 2 files, you specify what HTML is rendered in your game client interface.
In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser.
Example: extract of "hearts_hearts.tpl":
<pre>
<div id="myhand_wrap" class="whiteblock">
<h3>{MY_HAND}</h3>
<div id="myhand">
</div>
</div>
</pre>
== WARNING ==
Your view and your template are supposed to generate only the BASE layout of the game
You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :)
Example of things to generate in your view:
* The overall layout of your game interface (what is displayed where).
* The board and fixed elements on the board (ex: places for cards, squares, ...).
Example of things that shouldn't be generate by your view:
* Game elements that come and go from the game area.
* Game elements that are moving from one place to another.
== phplib template system ==
BGA is using the phplib template system, used for example in PHPbb forums.
More details about how to use phplib template system here:
http://www.phpbuilder.com/columns/david20000512.php3
== Variables ==
In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value.
In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}".
To give a value to this variable in your view.php:
Examples:
<pre>
// Display a translated version of "My hand" at the place of the variable in the template
$this->tpl['MY_HAND'] = self::_("My hand");
// Display some raw HTML material at the place of the variable
$this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" );
</pre>
== Blocks ==
Using "blocks", you can repeat a piece of HTML from your template several time.
You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares:
<pre>
(in reversi_reversi.tpl)
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
<div id="discs">
</div>
</div>
(in reversi.view.php)
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Explanations:
* You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square".
* In your view, you declare your block using "begin_block" method.
* Then, you can insert as many block as you want to, using "insert_block" method.
The insert_block method takes 2 parameters:
* the name of the block to insert.
* an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP).
== Nested blocks ==
You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it:
<pre>
(In template file)
<!-- BEGIN player -->
<div class="miniboard" id="miniboard_{PLAYER_ID}">
<div class="card_places">
<!-- BEGIN card_place -->
<div id="card_place_{PLAYER_ID}_{PLACE_ID}">
</div>
<!-- END card_place -->
</div>
</div>
<!-- END player -->
(In view file)
$this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first
$this->page->begin_block( "mygame_mygame.tpl", "player" );
foreach( $players as $player_id => $player )
{
// Important: nested block must be reset here, otherwise the second player miniboard will
// have 8 card_place, the third will have 12 card_place, and so one...
$this->page->reset_subblocks( 'card_place' );
for( $i=1; $i<=4; $i++ )
{
$this->page->insert_block( "card_place", array(
'PLAYER_ID' => $player_id,
'PLACE_ID' => $i
);
}
$this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id );
}
</pre>
== Javascript templates ==
For game elements that come and go from the game area, we suggest you to define a Javascript template.
A Javascript template is defined in your template file like this:
(Reversi Token from Reversi example):
<pre>
<script type="text/javascript">
// Templates
var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>';
</script>
</pre>
Note: a section for javascript templates is already available at the end of your template skeleton file.
Then, you can use this javascript template to insert this piece of HTML in your game interface, like this:
<pre>
dojo.place( this.format_block( 'jstpl_disc', {
xy: x+''+y,
color: color
} ) , 'discs' );
</pre>
== How to access game information from .view.php? ==
From your .view.php, you can access the following:
=== Access current player id===
<pre>
global $g_user;
$current_player_id = $g_user->get_id();
</pre>
=== Access game object ===
In your view file, "$this->game" contains an instance of your main game class.
Example:
<pre>
// Access to some game elements description described in your "material.inc.php":
$my_cards_types = $this->game->card_types;
// Access to any (public) method defined in my .game.php file:
$result = $this->game->myMethod();
</pre>
== Tips: displaying a nice button ==
From time to time, you need to display a standard button in your interface. BGA framework provides you a standard button that you can use directly in your interface:
<pre>
<a href="#" id="my_button_id" class="button"><span>My button label</span></a>
</pre>
Note: To see it in action, check for example a Coloretto game
a196c46198d60716daa784c0ab70e4b05830ccef
Gamehelplibertalia
0
105
689
2013-03-13T13:45:03Z
Peshte
2675
Created page with " == '''How to Play:''' == When it comes down to it, the actual game play of Libertalia is fair simple. Each player has a (mostly) identical set of crew cards. At the start of..."
wikitext
text/x-wiki
== '''How to Play:''' ==
When it comes down to it, the actual game play of Libertalia is fair simple. Each player has a (mostly) identical set of crew cards. At the start of each round, one player deals out 9 crew members and reads them out loud to the rest of the players. Each other player then finds the same cards and pulls them into their hands. Thus, each round, players are playing with the same crew cards.
Each crew card will have a strength (representing what order they choose their booty), and a special ability. Each card also has a tie breaker number, in case 2 players chose the same crew card.
Once you have your hand of 9 cards, play begins. Each campaign is broken up into 6 days of looting. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the main pirate ship in decreasing order. At this phase, any special actions that take place during sunrise would happen. Players also will need to use the tie breaker number on any crew cards if 2 or more people played the same crew member.
'''''Phase 2: Day'''''
The only thing that happens in this phase is any crew member with a day action, may take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Now, each player chooses a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2). So your high ranking cards will get you the best tokens. Also, any dusk actions happen now.
'''''Phase 4: Night'''''
Once again, the only thing that happens in this phase is crew members may use their Night actions. The difference here though, is any crew members in your cabin, may still use their night actions. So that Barkeep card you played on day 1 of the current round, (his action is to score you 1 doubloon each night) will keep paying you each night of the campaign. Play those night cards early!
After the 6th day of the campaign, the round is over. Players resolve any “end of campaign” actions of crew members till alive in their dens (yes, crew members can be killed). Then, each player adds up the value of their booty tokens and moves their score marker ahead on the track.
To reset for the next campaign, all crew members used are removed from the game, all doubloons are returned to the bank (except 10) and all booty tokens returned to the bag.
The key here is each player should have 3 cards left in their hand. They can use those in the next 2 campaigns. So everyone will have a somewhat different hand going forward.
To start the next round, someone draws 6 new crew cards and everyone else takes the matching cards into their hand. Round 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
fed7d8854a5c6ec97249e9f74e82bb1b264bbda4
690
689
2013-03-15T02:06:17Z
Jirikki
2655
/* How to Play: */
wikitext
text/x-wiki
== '''How to Play:''' ==
In the first round, all players have an identical random set of 9 crew cards. For rounds 2 and 3, each player gets 6 identical cards to add to their 3 left over cards which may be different from the other players.
Each crew card has a strength rating and a tie breaker number (representing what order they choose their booty), and a special ability. Crew are arranged with the lowest rating to highest, left to right.
The games consists of 3 campaigns, broken up into 6 days of looting. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the main pirate ship in decreasing order. At this phase, any special actions that take place during sunrise would happen. Players also will need to use the tie breaker number on any crew cards if 2 or more people played the same crew member.
'''''Phase 2: Day'''''
The only thing that happens in this phase is any crew member with a day action, may take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Now, each player chooses a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2). So your high ranking cards will get you the best tokens. Also, any dusk actions happen now.
'''''Phase 4: Night'''''
Once again, the only thing that happens in this phase is crew members may use their Night actions. The difference here though, is any crew members in your cabin, may still use their night actions. So that Barkeep card you played on day 1 of the current round, (his action is to score you 1 doubloon each night) will keep paying you each night of the campaign. Play those night cards early!
After the 6th day of the campaign, the round is over. Players resolve any “end of campaign” actions of crew members till alive in their dens (yes, crew members can be killed). Then, each player adds up the value of their booty tokens and moves their score marker ahead on the track.
To reset for the next campaign, all crew members used are removed from the game, all doubloons are returned to the bank (except 10) and all booty tokens returned to the bag.
The key here is each player should have 3 cards left in their hand. They can use those in the next 2 campaigns. So everyone will have a somewhat different hand going forward.
To start the next round, someone draws 6 new crew cards and everyone else takes the matching cards into their hand. Round 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
4c777c2b3b9d498869f1c54787c435ab9785bb6d
691
690
2013-03-15T02:37:17Z
Jirikki
2655
/* How to Play: */
wikitext
text/x-wiki
== '''How to Play:''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action MUST take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed and action resolved (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
1a01f4d4b2394c68ed674410180a76eeed5666ba
692
691
2013-03-15T02:51:17Z
Jirikki
2655
/* How to Play: */
wikitext
text/x-wiki
== '''How to Play:''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure.
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
71d48d5c00cb880cbfa1f5ce67e03c79c5e6fbc4
693
692
2013-03-15T09:27:35Z
Jirikki
2655
/* How to Play: */
wikitext
text/x-wiki
Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that make Libertalia original is that everyone start with the same set of cards. That's why you'll have to choose carefully the moment to play each card, and to try to read your opponents' strategies.
[[Link title]]== '''How to Play:''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure.
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
598bdc92946072ab19c78566b75e9983707d93ea
토론:Gamehelpquoridor
1
106
694
2013-03-16T17:33:33Z
Sirius136
2706
步步為營(zh)
wikitext
text/x-wiki
[http://heyjude0929.pixnet.net/blog/post/26923277-%5B%E9%81%8A%E6%88%B2%E4%BB%8B%E7%B4%B9%5D%E6%AD%A5%E6%AD%A5%E7%82%BA%E7%87%9Fquoridor]
a555fdcb2abc183558136d2652fdb38e4a8911cd
토론:Gamehelptakenoko
1
107
698
2013-03-17T14:19:18Z
Maman tuture
2711
Created page with "Guide de référence rapide Chaque tour se compose de 2 étapes: 1) Choisir le Types de temps 2) Achever des objectifs, en effectuant 2 actions différentes Types de temps (..."
wikitext
text/x-wiki
Guide de référence rapide
Chaque tour se compose de 2 étapes:
1) Choisir le Types de temps
2) Achever des objectifs, en effectuant 2 actions différentes
Types de temps (toujours facultatif) :
Soleil - prendre une 3ème action
Pluie - cultiver 1 bambou sur n'importe quelle parcelle irrigué
Vent - prendre deux actions identiques
Tempête - déplacer le panda sur n'importe quelle parcelle,le panda mange un bambou comme d'habitude, si il n'y a pas d'aménagement d'interdiction de panda sur la parcelle
Nuages - choisir 1 des 4 autres types de temps pour ce tour ou prendre une puce d'aménagement
Aménagements - Des aménagements peuvent être placés que sur des parcelles qui n'ont pas de bambou. Il ne peut y avoir qu'un aménagement par parcelle et une fois placé, ne peut pas être modifié.
Actions :
Parcelle - Les Parcelles ne peuvent être placés que de façon adjacents à l'étang ou lorsqu'elles sont à côté de 2 autres parcelles en jeu.
Irrigation - Les canaux d'irrigation doivent être installé entre deux parcelles. Quand une parcelle est irriguée pour la première fois il y pousse un bambou.
Jardinier - Le jardinier fait pousser du bambou sur la parcelle ou il se déplace et sur toutes les parcelles irriguées adjacentes de la même couleur et se déplace en ligne droite
Panda - le panda mange un bambou, si il n'y a pas d'aménagement interdiction panda sur la parcelle et se déplace en ligne droite
Le jeu se termine quand un certain nombre d'objectifs ont été réalisés.
2 joueurs - 9 objectifs
3 joueurs - 8 objectifs
4 joueurs - 7 objectifs
Le premier joueur qui a compléter le nombre requis d'objectifs déclenche la phase finale et obtiens une carte bonus de 2 points supplémentaire. Les autres joueurs ont un tour final.
Le score le plus élevé gagne, c'est la calcul du nombre de points sur les objectifs panda qui départage un score a égalité. Si le score reste toujours à égalité, tous les joueurs à égalité ont gagner.
b9dd55bf908ecc24830088f1deb125a28474416c
Your game state machine: states.inc.php
0
90
702
486
2013-03-23T10:33:02Z
Tirix
1962
Corrected 'arg'=>'args'
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"args" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "placeWorkers",
"description" => clienttranslate('${actplayer} must place some workers'),
"descriptionmyturn" => clienttranslate('${you} must place some workers'),
"type" => "activeplayer",
"args" => "argPlaceWorkers", <================================== HERE
"possibleactions" => array( "placeWorkers" ),
"transitions" => array( "nextPlayer" => 11, "nextPhase" => 12, "zombiePass" => 11 )
),
</pre>
It corresponds to a « argPlaceWorkers » method in our PHP code (reversi.game.php):
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves()
);
}
</pre>
Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn :
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above).
Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn).
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
4223897f52eb3a5079cf418baa10823bc4df3b16
714
702
2013-03-28T17:34:44Z
Sourisdudesert
1
/* args */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"args" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn", <================================== HERE
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
</pre>
It corresponds to a « argPlaceWorkers » method in our PHP code (reversi.game.php):
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves()
);
}
</pre>
Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn :
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above).
Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn).
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
ab9b17a0876a9a2f896473a45b3f21902d84d563
729
714
2013-04-05T02:46:37Z
Pikiou
1872
/* args */ returned value from the arg function must be an associative array
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"args" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn", <================================== HERE
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
</pre>
It corresponds to a « argPlaceWorkers » method in our PHP code (reversi.game.php):
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves()
);
}
</pre>
Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn :
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above).
Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn).
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
1e0d2ec9b66998ded171afa7edc9b10a50663aa9
Gamehelpcantstop
0
35
703
635
2013-03-24T14:06:08Z
Een
3
Chinese translation moved to Chinese wiki
wikitext
text/x-wiki
Can't Stop is a very easy and fast game!
'''How to play'''
Roll 4 standard dice and then choose the sums of any 2 dice to advance your position on the board. You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have fewer.
'''The object of the game is''' to reach and cover 3 peaks of these columns!
ed20a83da52065513f496d9eca15f358aaa88395
Gamehelpcaylus
0
37
704
108
2013-03-24T14:10:25Z
Een
3
Rules link updated in the game page, obsolete information removed
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelpcoloretto
0
33
705
658
2013-03-24T14:13:28Z
Een
3
Move German text to German wiki
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelpunitedsquare
0
42
706
155
2013-03-24T14:24:23Z
Een
3
Adding info about colorblind preference
wikitext
text/x-wiki
==Goal==
The goal is to be the player who has the most squares of his colors.
==Rules==
The game contains multicolored squares (red, blue. yellow and green) which appear as 4 colored triangles on the square.
Each player on his turn puts a multicolored square next to a square already on the board. The played square (which can be shifted to fit as requested, keeping the order of the colors the same) must be put in a way that creates at least on colored square (not necessarily your color). If it is not possible for the player to put down a square, the turn is passed to the next player.
It is also possible to have "non playable" squares which are created when 2 of the same color are connected to the same open square. This is also a strategy to prevent from your opponent from getting more squares of his color. (e.g. if there is a red triangle facing an empty square and i connect to that same empty square another red triangle from another side, the empty square cannot be played and all colors around the "non playable" square will not become squares and won't gain points).
==Ending the game==
When all playable squares have been played, the player with the most squares of his color wins the game.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD].
Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
HAVE A GOOD GAME!
ae79857f1a4a6c81a32e01211140a120a3b1acf4
707
706
2013-03-24T14:28:18Z
Een
3
wikitext
text/x-wiki
==Goal==
The goal is to be the player who has the most squares of his colors.
==Rules==
The game contains multicolored squares (red, blue. yellow and green) which appear as 4 colored triangles on the square.
Each player on his turn puts a multicolored square next to a square already on the board. The played square (which can be shifted to fit as requested, keeping the order of the colors the same) must be put in a way that creates at least on colored square (not necessarily your color). If it is not possible for the player to put down a square, the turn is passed to the next player.
It is also possible to have "non playable" squares which are created when 2 of the same color are connected to the same open square. This is also a strategy to prevent from your opponent from getting more squares of his color. (e.g. if there is a red triangle facing an empty square and i connect to that same empty square another red triangle from another side, the empty square cannot be played and all colors around the "non playable" square will not become squares and won't gain points).
==Ending the game==
When all playable squares have been played, the player with the most squares of his color wins the game.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD].
Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
'''HAVE A GOOD GAME!'''
694ca001b63acf097dcc5297944ab9994a7ef0b8
Gamehelptroyes
0
26
708
665
2013-03-24T14:51:54Z
Een
3
Revert to English in the English wiki. German has been moved to the German wiki
wikitext
text/x-wiki
== Goal ==
Be the player with the most victory points at the end of the game.
== Rules summary ==
(This rules summary is based on the game help written by [http://boardgamegeek.com/user/pregremlin Andrew Agard] for Board Game Geek, under Creative Commons license. Please see [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] here for details. Thank you Andrew !)
===Initial Placement===
* In clockwise order place a citizen in empty space of one building
* Continue in counter clockwise order from last player and so on until all citizens placed
===Game play===
====Phase 0: Reveal the Activity cards====
Reveal activity card for each color corresponding to current round (first 3 rounds only)
====Phase 1: Income and salaries====
Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP
====Phase 2: Assembling the workforce====
Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district
====Phase 3: Events====
Reveal top red and white or yellow Event and place to right of queue (unlimited Events)
Events take effect from left to right
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Actions====
See below.
====Phase 5: End of the round====
Receive deniers from district
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Pass start player card left.
===Actions===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Activate Activity Card====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Combat Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Place a citizen on building====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Use Agriculture====
* Gain number of deniers equal to total value divided by 2 (round down)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
Have a good game !
fbdfaed8129e77bd038dee3623968940c24674a0
Tutorial gomoku
0
73
709
407
2013-03-24T18:38:25Z
Een
3
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( '../../img/gomoku/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
// At the end of the slide, update the intersection
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' );
dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color );
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
// We can now destroy the stone since it is now visible through the change in style of the intersection
dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y );
}));
slide.play();
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
9d1e093ea97321f4d3cd5a98ab0acf194aa21aa5
Gamehelphaggis
0
22
710
48
2013-03-25T05:43:15Z
Manchuwok
2352
/* Goal */
wikitext
text/x-wiki
== Goal ==
Earn more points than your opponent(s). Points may be earned by emptying your hand before the other players, capturing cards during play, and betting that you will be first to shed all of your cards.
== Rules summary ==
A valid card combination may be a set, a sequence or a bomb:
* a "set" is a group of any number of cards of the same rank (ex: one "8", two "5", ...).
* a "sequence" is a group of 3 or more cards of the same color with consecutive rank (ex: red 8, red 9, red 10)
* a "sequence" can also be a group of 2 or more pairs or larger sets of consecutive rank sharing the same suits between sets (ex: blue 3, green 3, blue 4, green 4, blue 5, green 5)
* a "bomb" is one of the following combination (ranked below from lowest to highest):
** 3-5-7-9 (in 4 different colors, "rainbow bomb")
** J-Q
** J-K
** Q-K
** J-Q-K
** 3-5-7-9 (in one color, "suited bomb")
Face cards can be used as wild cards to replace any cards in a "set" or a "sequence". Each player starts a round with a Jack, a Queen and a King. These face cards are public.
At your turn, you have to play a higher ranking combination with exactly the same type and same number of card that the first combination played. You can also pass. Bombs are an exception: you can play a bomb to beat any combination, except a higher bomb.
When all but one player pass in succession, the player who played the highest combination capture all cards played. Important exception: if the highest combination is a bomb, cards are captured by the player with the next higher combination. Then, a new trick starts. The winner of the last trick leads the new trick with any combination.
===Scoring overview===
* At the moment you shed your last card: 5 points per card in the hand of the player who held the most cards.
* Cards captured values: 2-4-6-8-10 = 0 point, 3-5-7-9 = 1 point, J = 2 points, Q = 3 points, K = 5 points.
* 30 points for a successful "Big bet", 15 points for a successful "Little bet". Points from unsuccessful bets are added to scores of the round's winner and to player(s) who did not bet.
154c77dae5ab153c37efd40d1286011b7c751d2a
Gamehelplibertalia
0
105
711
693
2013-03-26T08:59:45Z
Kevlarrelic
2786
Corrected some grammar in the introduction. I am an english teacher. It's what I do. :)
wikitext
text/x-wiki
Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies.
[[Link title]]== '''How to Play:''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure.
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
869176603f34509754ff42de70dd9f95d2127be5
737
711
2013-04-08T16:12:40Z
Nalafab
2897
wikitext
text/x-wiki
Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies.
== '''How to Play''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure.
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
47efc3c935f3f435ca534667540ffbd44fe68780
Grade
0
30
712
70
2013-03-26T19:47:56Z
Doomquill
2742
/* All grades */
wikitext
text/x-wiki
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== All grades ==
* '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel).
* '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points.
* '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade.
* '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased.
* '''Archangel''': this is the Board Game Arena administrators' grade.
* '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time.
* '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...)
8227839171a768ad8ec8be6d69d0eb3af8e1b5d4
Gamehelpseasons
0
43
713
669
2013-03-26T20:45:50Z
Doomquill
2742
Clarification of rule: Cards are discarded with no refund if summoned by use of another card, but there is no room for them.
wikitext
text/x-wiki
Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
Star - increase the maximum card player can summon (max 15)
Elements - Gain an energy of the element shown (water, earth, air, fire)
Numbers - Gain the number of Crystals as indicated by the number
Square card - Draw a card
Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at)
Dots - Indicate how fast the marker progress through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund.
e983a49ace608ec6898446f1ac07707648c0d7d4
Gamehelpsenet
0
108
715
2013-03-30T14:17:42Z
Kara thrace
2819
Created page with " == Summary == Senet ("''The Game of Passing Through the Netherworld''") is well over 5000 yrs old, and is therefore most probably the oldest boardgame ever known. It comes f..."
wikitext
text/x-wiki
== Summary ==
Senet ("''The Game of Passing Through the Netherworld''") is well over 5000 yrs old, and is therefore most probably the oldest boardgame ever known. It comes from the ancient Egypt, where it was used to amuse people and serve as a religional metaphor for the human souls' journey towards a blessed afterlife.
Senet is an elegant and quick blocking game for 2 players, who compete against each other by moving their own pawns across a gameboard of thirty squares. Despite its old age, Senet turns out to be an amusing and tense little game for today's gamers aswell.
== Goal ==
Move your stones (one at a time) on a reverse "S"'-shaped gametrack from the upper left to the lower right corner of the gameboard, where they can leave the gamearea.
Be the first to bear all your stones off the gameboard to win!
== The four "casting sticks" ==
The thrown sticks determine, how far you can move a stone during your turn.
How to read the sticks:
Count the sticks with their light sides up (results can be: 1, 2, 3 or 4).
If no light sides show up at all - that's counted as a result of 5.
Throwing values of 1, 4 and 5 grant Extra Turns.
== Movement rules ==
If your stone lands on the opponent's unprotected stone, they swap places.
You cannot land on a stone of your own colour.
Two or more adjacent stones of the same colour protect each other.
You always have to try to do a forward move. If this is not possible, you have to move one of your stones backwards.
If you have NO valid moves to make at all - you loose your turn.
Stones on the last 4 gamefields are never protected and cannot be moved - just borne off.
== Special gamefields ==
Field 26 ('The House of Beauty'): All stones must STOP here on an exact throw, before they can go further. A stone standing here can be borne off the board on an exact throw of 5.
Field 27 ('The House of Waters'): This is a pitfall! If you have a stone 'drowning' here, you have to decide whether to return the stone to Field 15 ('The House of Second Life') or to take the sticks and risk to throw a value of 4. (If you succeed to throw a 4 - the stone is borne off).
Field 28 ('The House of Three Judges'): A stone standing here, can be borne off the board by an exact throw of 3.
Field 29 ('The House of Two Judges'): A stone standing here, can be borne off the board by an exact throw of 2.
Field 30 ('The House of Horus'): A stone standing here, can be borne off the board by ANY throw.
If a stone is attacked on the last 3 gamefields, it is dropped into the "water" (unless the House of Waters is occupied already).
Be the first to bear all your stones off the gameboard!
d50b8a464add1615915b7573b6889b85318a277f
716
715
2013-03-30T14:18:07Z
Kara thrace
2819
/* Special gamefields */
wikitext
text/x-wiki
== Summary ==
Senet ("''The Game of Passing Through the Netherworld''") is well over 5000 yrs old, and is therefore most probably the oldest boardgame ever known. It comes from the ancient Egypt, where it was used to amuse people and serve as a religional metaphor for the human souls' journey towards a blessed afterlife.
Senet is an elegant and quick blocking game for 2 players, who compete against each other by moving their own pawns across a gameboard of thirty squares. Despite its old age, Senet turns out to be an amusing and tense little game for today's gamers aswell.
== Goal ==
Move your stones (one at a time) on a reverse "S"'-shaped gametrack from the upper left to the lower right corner of the gameboard, where they can leave the gamearea.
Be the first to bear all your stones off the gameboard to win!
== The four "casting sticks" ==
The thrown sticks determine, how far you can move a stone during your turn.
How to read the sticks:
Count the sticks with their light sides up (results can be: 1, 2, 3 or 4).
If no light sides show up at all - that's counted as a result of 5.
Throwing values of 1, 4 and 5 grant Extra Turns.
== Movement rules ==
If your stone lands on the opponent's unprotected stone, they swap places.
You cannot land on a stone of your own colour.
Two or more adjacent stones of the same colour protect each other.
You always have to try to do a forward move. If this is not possible, you have to move one of your stones backwards.
If you have NO valid moves to make at all - you loose your turn.
Stones on the last 4 gamefields are never protected and cannot be moved - just borne off.
== Special gamefields ==
* Field 26 ('The House of Beauty'): All stones must STOP here on an exact throw, before they can go further. A stone standing here can be borne off the board on an exact throw of 5.
* Field 27 ('The House of Waters'): This is a pitfall! If you have a stone 'drowning' here, you have to decide whether to return the stone to Field 15 ('The House of Second Life') or to take the sticks and risk to throw a value of 4. (If you succeed to throw a 4 - the stone is borne off).
* Field 28 ('The House of Three Judges'): A stone standing here, can be borne off the board by an exact throw of 3.
* Field 29 ('The House of Two Judges'): A stone standing here, can be borne off the board by an exact throw of 2.
* Field 30 ('The House of Horus'): A stone standing here, can be borne off the board by ANY throw.
If a stone is attacked on the last 3 gamefields, it is dropped into the "water" (unless the House of Waters is occupied already).
Be the first to bear all your stones off the gameboard!
db8e2cd5d5a4e02c8a00c5ef8d237c29b86e91bb
How to join BGA developer team?
0
83
717
521
2013-03-30T17:10:00Z
Een
3
wikitext
text/x-wiki
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your player user name on BGA
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf ''''terms & conditions' document''']. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: ''''I agree with the terms & conditions for developers on BGA Studio joined as an attachment''''.
And of course, we also encourage you to tell us about which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, we'll discuss by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a 'resources.html' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... that's all, you can start!
cecd170b97b99a88d4541f8073f7d553d671aaf7
740
717
2013-04-13T12:27:37Z
Een
3
wikitext
text/x-wiki
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your player user name on BGA
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf ''''terms & conditions' document''']. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: ''''I agree with the terms & conditions for developers on BGA Studio joined as an attachment''''.
And of course, we also encourage you to tell us about your developer experience and which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, we'll discuss by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
Second, once we have discussed together and are set on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a ''''resources.html'''' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... well that's all, you can start! See [[Studio#Great.2C_I.27m_in.21_..._How_should_I_start.3F|Great, I'm in! ... How should I start?]]
9c82f85a3c558b3f7a584d879031b343438217f5
Game database model: dbmodel.sql
0
92
718
601
2013-03-31T13:24:39Z
Rudolf
2790
/* Default tables */
wikitext
text/x-wiki
In this file you specify the database schema of your game.
This file contains SQL queries that will be executed during the creation of your game table.
Note: you can't change the database schema during the game.
== Create your schema ==
To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file.
== Default tables ==
Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player.
You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code).
You may add columns to "player" table. This is very practical to add simple values associated with players.
Example:
<pre>
ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7';
</pre>
For your information, the useful columns of default "player" table are:
* player_no: the index of player in natural playing order.
* player_id
* player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods)
* player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores.
* player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game (see also: [[Main_game_logic:_yourgamename.game.php#Manage_player_scores_and_Tie_breaker|Manage_player_scores_and_Tie_breaker]])
== CREATE TABLES ==
you can create tables, using engine InnoDB
<pre>
CREATE TABLE IF NOT EXISTS `hands`
(
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`player_id` TINYINT(1) NOT NULL,
`1` BOOL NOT NULL DEFAULT 1,
`2` BOOL NOT NULL DEFAULT 1,
`3` BOOL NOT NULL DEFAULT 1,
`4` BOOL NOT NULL DEFAULT 1,
`5` BOOL NOT NULL DEFAULT 1,
`6` BOOL NOT NULL DEFAULT 1,
`7` BOOL NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
'''Note''': if you put comments, you cannot do it in same line than code,
<pre>
`3` BOOL NOT NULL DEFAULT 1, --
</pre>
will comment also starting from `3` BOOL, and code will not be taken into account.
== Link ==
You can add your Db inits in function SetupNewGame() from file 'gamename.game.php'
== Errors Log ==
To trace Database creation, you've got a small summun up in red bars during the game, but details are in logs that you can access in /admin/studio.
2a8a849c1614262e9ba8dbfebfa54de8e18e4677
719
718
2013-03-31T13:26:02Z
Rudolf
2790
/* CREATE TABLES */ activated
wikitext
text/x-wiki
In this file you specify the database schema of your game.
This file contains SQL queries that will be executed during the creation of your game table.
Note: you can't change the database schema during the game.
== Create your schema ==
To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file.
== Default tables ==
Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player.
You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code).
You may add columns to "player" table. This is very practical to add simple values associated with players.
Example:
<pre>
ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7';
</pre>
For your information, the useful columns of default "player" table are:
* player_no: the index of player in natural playing order.
* player_id
* player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods)
* player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores.
* player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game (see also: [[Main_game_logic:_yourgamename.game.php#Manage_player_scores_and_Tie_breaker|Manage_player_scores_and_Tie_breaker]])
== CREATE TABLES ==
you can create tables, using engine InnoDB
<pre>
CREATE TABLE IF NOT EXISTS `hands`
(
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`player_id` TINYINT(1) NOT NULL,
`1` BOOL NOT NULL DEFAULT 1,
`2` BOOL NOT NULL DEFAULT 1,
`3` BOOL NOT NULL DEFAULT 1,
`4` BOOL NOT NULL DEFAULT 1,
`5` BOOL NOT NULL DEFAULT 1,
`6` BOOL NOT NULL DEFAULT 1,
`7` BOOL NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
'''Note''': if you put comments, you cannot do it in same line than code,
<pre>
`3` BOOL NOT NULL DEFAULT 1, -- activated or not
</pre>
will comment also starting from `3` BOOL, and code will not be taken into account.
== Link ==
You can add your Db inits in function SetupNewGame() from file 'gamename.game.php'
== Errors Log ==
To trace Database creation, you've got a small summun up in red bars during the game, but details are in logs that you can access in /admin/studio.
b66632e64543242efff3183de07348b143ce422d
Studio
0
49
720
575
2013-03-31T13:31:10Z
Rudolf
2790
/* Other components */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
044e82a5e514797137b0960b427392296a307c6c
738
720
2013-04-13T12:20:43Z
Een
3
/* Discover BGA Studio in 5 presentations */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
49bd82e187e809424e09a921d09087648e29041a
739
738
2013-04-13T12:21:12Z
Een
3
/* How to join the BGA developer team? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
a639c5429d43182a1d03f41eb76931d1ee5e12ee
741
739
2013-04-13T12:28:58Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we would advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
c43891a136c278b4cc82d5a748fe45170d32aad5
742
741
2013-04-13T12:29:17Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
[[Studio FAQ]]
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
6dcd18e33a284bb4a37226504c1a3706163522ed
743
742
2013-04-13T12:30:15Z
Een
3
/* BGA Studio documentation */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
2d3092714cdd13c4a5f879634984870268c47799
744
743
2013-04-13T12:31:55Z
Een
3
/* Great, I'm in! ... How should I start? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
f99220401e370693553bd434ceedcfd982b9b526
745
744
2013-04-13T12:34:53Z
Een
3
/* BGA Studio game components reference */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
893b70581489f7ff082e842dd3679fc3eebcb54f
746
745
2013-04-13T12:35:51Z
Een
3
/* BGA Studio user guide */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
== BGA Studio user guide ==
This part of the documentation is a user guide for the BGA Studio online development environment.
[[Tools and tips of BGA Studio]]
[[Practical debugging]]
[[Studio back-office]]
[[Studio FAQ]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
959f22824e9f3872dbf33d27215a865a48064e04
747
746
2013-04-13T12:36:20Z
Een
3
/* BGA Studio user guide */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focus on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
== BGA Studio user guide ==
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio back-office]]
* [[Studio FAQ]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
9d2e8115976c14cc5292502715452c16a798e93a
749
747
2013-04-13T13:38:01Z
Een
3
/* BGA Studio documentation */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
== BGA Studio user guide ==
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio back-office]]
* [[Studio FAQ]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
d3aee79969dfa85c8c291868d0d0ca64cd86c429
750
749
2013-04-13T13:38:25Z
Een
3
/* BGA Studio user guide */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio back-office]]
* [[Studio FAQ]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
33524cca8777e21c41c941b4b654ccc66ead291a
751
750
2013-04-13T13:38:56Z
Een
3
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio back-office]]
* [[Studio FAQ]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
cedd0f7bf28e85bb5b1e5f8b3c8524a1f6485e41
Game replay
0
109
721
2013-03-31T13:31:32Z
Rudolf
2790
Created page with "Game replay is managed by the framework (through replaying javascript notifications). You do not need to do anything special about it in your code."
wikitext
text/x-wiki
Game replay is managed by the framework (through replaying javascript notifications).
You do not need to do anything special about it in your code.
2152a2539ed7c895c8f6d92c2a5c3c17b21e2612
Tools and tips of BGA Studio
0
99
722
579
2013-03-31T13:44:45Z
Rudolf
2790
Dev Tips
wikitext
text/x-wiki
== Starting a game in one click ==
To start a game:
* Create a new table with your game.
* If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table.
* Click on "Express Start".
== Stopping a game in one click ==
* Click on the "quit" icon on the top right of the screen.
* Click on "Express Stop".
== Switching between users ==
when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective.
== Access to game database ==
Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game.
== Save & restore state ==
Using links of this section, you can save the complete current (database) state of your game, then restore it later.
This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine.
We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations.
Limits:
* the "restore" function does not work anymore when the game is over.
* a saved situation from a given table cannot be restored in another table.
* when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually.
== Input/Output debugging section ==
This section shows you:
* The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">"
* The notifications received by your game interface. Notifications (inputs) begins with "<".
Note: if you click on some notification title, you can resend it immediately to the user interface.
== Run from the chat ==
On BGA Studio, you can directly run a PHP method from the chat.
For example, if on your PHP you have this method:
<pre>
function giveMoneyToPlayer($player_id, $amount)
{
// Do some stuff
}
</pre>
You can call this method directly from the chat like this: "giveMoneyToCurrentPlayer(2564,2)".
== Dev Tips ==
'''Edit TPL''' <p>
To edit TPL with HTML code highlightings in Gedit under Ubuntu:
find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...)
Here it's 3.0, then type in a terminal window:
<pre>
sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang
</pre>
then find 'globs' section, and change:
<pre>
<property name="globs">*.html;*.htm;*.tpl</property>
</pre>
367271135966a60f7d8667032e164ba115fad7a7
723
722
2013-03-31T13:45:37Z
Rudolf
2790
/* Dev Tips */
wikitext
text/x-wiki
== Starting a game in one click ==
To start a game:
* Create a new table with your game.
* If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table.
* Click on "Express Start".
== Stopping a game in one click ==
* Click on the "quit" icon on the top right of the screen.
* Click on "Express Stop".
== Switching between users ==
when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective.
== Access to game database ==
Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game.
== Save & restore state ==
Using links of this section, you can save the complete current (database) state of your game, then restore it later.
This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine.
We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations.
Limits:
* the "restore" function does not work anymore when the game is over.
* a saved situation from a given table cannot be restored in another table.
* when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually.
== Input/Output debugging section ==
This section shows you:
* The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">"
* The notifications received by your game interface. Notifications (inputs) begins with "<".
Note: if you click on some notification title, you can resend it immediately to the user interface.
== Run from the chat ==
On BGA Studio, you can directly run a PHP method from the chat.
For example, if on your PHP you have this method:
<pre>
function giveMoneyToPlayer($player_id, $amount)
{
// Do some stuff
}
</pre>
You can call this method directly from the chat like this: "giveMoneyToCurrentPlayer(2564,2)".
== Dev Tips ==
'''Edit TPL''' <p>
To edit TPL with HTML code highlightings in Gedit under Ubuntu:
find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...).<p>
Here it's 3.0, then type in a terminal window:
<pre>
sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang
</pre>
then find 'globs' section, and change:
<pre>
<property name="globs">*.html;*.htm;*.tpl</property>
</pre>
dce08d9c2bca925f260d93beb64ba667c5346b0e
724
723
2013-03-31T13:47:11Z
Rudolf
2790
/* Dev Tips */
wikitext
text/x-wiki
== Starting a game in one click ==
To start a game:
* Create a new table with your game.
* If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table.
* Click on "Express Start".
== Stopping a game in one click ==
* Click on the "quit" icon on the top right of the screen.
* Click on "Express Stop".
== Switching between users ==
when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective.
== Access to game database ==
Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game.
== Save & restore state ==
Using links of this section, you can save the complete current (database) state of your game, then restore it later.
This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine.
We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations.
Limits:
* the "restore" function does not work anymore when the game is over.
* a saved situation from a given table cannot be restored in another table.
* when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually.
== Input/Output debugging section ==
This section shows you:
* The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">"
* The notifications received by your game interface. Notifications (inputs) begins with "<".
Note: if you click on some notification title, you can resend it immediately to the user interface.
== Run from the chat ==
On BGA Studio, you can directly run a PHP method from the chat.
For example, if on your PHP you have this method:
<pre>
function giveMoneyToPlayer($player_id, $amount)
{
// Do some stuff
}
</pre>
You can call this method directly from the chat like this: "giveMoneyToCurrentPlayer(2564,2)".
== Dev Tips ==
'''Edit TPL''' <p>
To edit TPL with HTML code highlightings in Gedit under Ubuntu:
find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...).
<br>
Here it's 3.0, then type in a terminal window:
<pre>
sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang
</pre>
then find 'globs' section, and change:
<pre>
<property name="globs">*.html;*.htm;*.tpl</property>
</pre>
eabf6d0dd309c1cc92989ad27bf93d72ed46cafa
Gamehelphearts
0
52
725
670
2013-04-02T09:29:12Z
Deluxus
20
Srca - Hearts
wikitext
text/x-wiki
Srca je igra z kartami za 4 igralce,ki jo igra vsak zase.Uporablja se standardni zavitek 52 kart.
'''Moč kart'''
A (najvišja) to 2 (najnižja).
'''Priprava na igro'''
Razdeli se celoten zavitek kart,vsak dobi 13 kart.Po pregledu 13 kart v rokah si izbereš 3 karte in jih podaš drugemu igralcu.
Vrstni red podajanja 3 kart: (1 igra) igralcu na svoji levi, (2 igra) igralcu nasproti , (3 igra) igralcu na svoji desni, (4 igra) brez podajanja 3 kart. Vrstni red podajanja se ponavlja dokler igra ni končana.
'''Igra'''
Po podaji 3 kart, začne igralec ki ima v roki križevo 2.
Vsak igralec mora slediti vrženi barvi.Če nima karte z isto bravo, lahko vrže katerokoli karto , katerekoli barve.Izjema : V prvem krogu ne mores vržti srca ali pikove Dame,če nimaš križa.
Najvišja karta vzame vzetek.Igralec ki vzame vzetek vrže naslednjo karto.
Srca iz roke ne smemo igrati dokler ne pade prvo srce,namesto druge barve.Pikova Dama pa se lahko igra kadarkoli.
'''Točkovanje'''
Po koncu vsakega kroga,vsako srce šteje -1 in pikova Dama -13.
Če ima en igralec vseh 13 scr in pikovo Damo ,torej vse točkovne vzetke piše igralec 0, vsi ostali igralci pa pišejo -26.
Kadar eden ali več igralcev pride na 0 ,je igra končana.Igralec z največ točkami zmaga.
'''Variante igre'''
Normal game je 100 točk.
Quick game je 75 točk.
0fd9b27e12cc0e7c59b96f292587355a8c5a1f53
726
725
2013-04-02T09:31:13Z
Deluxus
20
Srca
wikitext
text/x-wiki
Srca je igra z kartami za 4 igralce,ki jo igra vsak zase.Uporablja se standardni zavitek 52 kart.
'''Moč kart'''
A (najvišja) do 2 (najnižja).
'''Priprava na igro'''
Razdeli se celoten zavitek kart,vsak dobi 13 kart.Po pregledu 13 kart v rokah si izbereš 3 karte in jih podaš drugemu igralcu.
Vrstni red podajanja 3 kart: (1 igra) igralcu na svoji levi, (2 igra) igralcu nasproti , (3 igra) igralcu na svoji desni, (4 igra) brez podajanja 3 kart. Vrstni red podajanja se ponavlja dokler igra ni končana.
'''Igra'''
Po podaji 3 kart, začne igralec ki ima v roki križevo 2.
Vsak igralec mora slediti vrženi barvi.Če nima karte z isto bravo, lahko vrže katerokoli karto , katerekoli barve.Izjema : V prvem krogu ne mores vržti srca ali pikove Dame,če nimaš križa.
Najvišja karta vzame vzetek.Igralec ki vzame vzetek vrže naslednjo karto.
Srca iz roke ne smemo igrati dokler ne pade prvo srce,namesto druge barve.Pikova Dama pa se lahko igra kadarkoli.
'''Točkovanje'''
Po koncu vsakega kroga,vsako srce šteje -1 in pikova Dama -13.
Če ima en igralec vseh 13 src in pikovo Damo ,torej vse točkovne vzetke piše igralec 0, vsi ostali igralci pa pišejo -26.
Kadar eden ali več igralcev pride na 0 ,je igra končana.Igralec z največ točkami zmaga.
'''Variante igre'''
Normal game je 100 točk.
Quick game je 75 točk.
0af950fd94f906473c28158f37df8967fd0fe100
Game interface logic: yourgamename.js
0
88
727
682
2013-04-02T15:45:08Z
Pikiou
1872
/* Tooltips */ addTooltip and addTooltipHtml get a node id, not a node element
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
87b3d23d52c75153c79cb900bcb8e2160e9aa782
728
727
2013-04-03T08:25:15Z
Sourisdudesert
1
/* Players input */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
68e1bb2388e4f34a0f12444cca0b8e51a5072093
Scrollmap
0
110
730
2013-04-08T12:26:19Z
Sourisdudesert
1
Created page with "Scrollmap is a BGA client side component to display an infinite game area. In many games, players are building the main game area with tiles or cards. Examples: * Carcassonne..."
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In many games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
For tiles placement games when player are building , the board can be "infinite"
cf4c11de919be13bbfdf77bb3e3610adf144ca01
732
730
2013-04-08T12:35:49Z
Sourisdudesert
1
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
f5870573733c23a47fbe7d00e3fe90f27b6a22f4
733
732
2013-04-08T12:54:34Z
Sourisdudesert
1
/* How to use Scrollmap */
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
2ab80d98e101873cfc58e10bc94bde0a24ac0ee3
734
733
2013-04-08T12:55:28Z
Sourisdudesert
1
/* Scrollable area layers */
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
44346c9a67f3757698a18a3d64803996ff5685d5
735
734
2013-04-08T12:58:51Z
Sourisdudesert
1
/* Scrollable area layers */
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
== Positioning elements on game area ==
All elements on the game are must be absolute positioned (with "top" and "left" attributes).
By default, the game area is centered on 0,0 coordinates.
e748822609d8cf4e816469a8a8b5eb157d898a16
736
735
2013-04-08T13:00:00Z
Sourisdudesert
1
/* How to use Scrollmap */
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area:
<pre>
/** Scrollable area **/
#map_container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
}
#map_scrollable, #map_scrollable_oversurface {
position: absolute;
top: 205px;
left: 315px;
}
#map_surface {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
cursor: move;
}
#map_footer {
text-align: center;
}
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
== Positioning elements on game area ==
All elements on the game are must be absolute positioned (with "top" and "left" attributes).
By default, the game area is centered on 0,0 coordinates.
eafd93396078275005cc7f744097c11c87c551a8
Stock
0
97
731
701
2013-04-08T12:33:20Z
Sourisdudesert
1
/* Using stock: a simple example */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
At first, don't forget to add "ebg/stock" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <==== HERE
],
</pre>
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
9052c361ca1eb2db288e379288080c355a3d2799
First steps with BGA Studio
0
111
748
2013-04-13T13:11:19Z
Een
3
Created page with "== Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * you..."
wikitext
text/x-wiki
== Connect to your SFTP folder and to the BGA Studio website ==
After your account has been created, you will get by email:
* the name of the SFTP server to connect to
* your SFTP login and password
* ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them.
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example)
# Check than in your home folder you have:
#* One folder for each of the three example games (reversi, hearts, gomoku)
#* One folder matching the game you will be developing
#* One 'resources.html' file
# Open the resources.html file, it contains
#* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file
#* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two)
#* The URL pointing to the web administration tool for the BGA Studio database.
# Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user.
== Launch your game and check how to update it ==
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
== Commit your changes ==
That's all! Now you know about the basics of updating your game on the studio and testing your changes!
1f6096bf4d1c068292d042c0363a4fa2c952d352
First steps with BGA Studio
0
111
752
748
2013-04-13T13:40:33Z
Een
3
/* Commit your changes */
wikitext
text/x-wiki
== Connect to your SFTP folder and to the BGA Studio website ==
After your account has been created, you will get by email:
* the name of the SFTP server to connect to
* your SFTP login and password
* ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them.
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example)
# Check than in your home folder you have:
#* One folder for each of the three example games (reversi, hearts, gomoku)
#* One folder matching the game you will be developing
#* One 'resources.html' file
# Open the resources.html file, it contains
#* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file
#* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two)
#* The URL pointing to the web administration tool for the BGA Studio database.
# Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user.
== Launch your game and check how to update it ==
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
== Commit your changes ==
Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development.
Here is how to go through your first commit:
# Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared);
# Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button;
# Check the log for errors, it should end with the following lines:
Transmitting file data .
Committed revision #revision number#.
HAL says: done.
NB: you should also commit each time you make an change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do it.
== That's all for your first steps! ==
Now you know about the basics of updating your game on the studio and testing your changes.
For more information on the specifics of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]].
2859dd460cb4e3a04a35a5cddab674d8644efd66
753
752
2013-04-13T13:41:04Z
Een
3
/* That's all for your first steps! */
wikitext
text/x-wiki
== Connect to your SFTP folder and to the BGA Studio website ==
After your account has been created, you will get by email:
* the name of the SFTP server to connect to
* your SFTP login and password
* ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them.
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example)
# Check than in your home folder you have:
#* One folder for each of the three example games (reversi, hearts, gomoku)
#* One folder matching the game you will be developing
#* One 'resources.html' file
# Open the resources.html file, it contains
#* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file
#* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two)
#* The URL pointing to the web administration tool for the BGA Studio database.
# Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user.
== Launch your game and check how to update it ==
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
== Commit your changes ==
Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development.
Here is how to go through your first commit:
# Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared);
# Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button;
# Check the log for errors, it should end with the following lines:
Transmitting file data .
Committed revision #revision number#.
HAL says: done.
NB: you should also commit each time you make an change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do it.
== That's all! ==
Now you know about the basics of updating your game on the studio and testing your changes.
For more information on the specifics of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]].
4eb92e9d60a7f84791aa477080ee79603d07e860
754
753
2013-04-13T13:41:24Z
Een
3
/* That's all! */
wikitext
text/x-wiki
== Connect to your SFTP folder and to the BGA Studio website ==
After your account has been created, you will get by email:
* the name of the SFTP server to connect to
* your SFTP login and password
* ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them.
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example)
# Check than in your home folder you have:
#* One folder for each of the three example games (reversi, hearts, gomoku)
#* One folder matching the game you will be developing
#* One 'resources.html' file
# Open the resources.html file, it contains
#* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file
#* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two)
#* The URL pointing to the web administration tool for the BGA Studio database.
# Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user.
== Launch your game and check how to update it ==
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
== Commit your changes ==
Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development.
Here is how to go through your first commit:
# Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared);
# Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button;
# Check the log for errors, it should end with the following lines:
Transmitting file data .
Committed revision #revision number#.
HAL says: done.
NB: you should also commit each time you make an change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do it.
== That's all! ==
Now you know about the basics of updating your game on BGA Studio and testing your changes.
For more information on the specifics of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]].
745c7b8b5751da1fe807c4d42c47542fbcf1d6ad
775
754
2013-04-21T21:50:04Z
Mlgx
2882
wikitext
text/x-wiki
== Connect to your SFTP folder and to the BGA Studio website ==
After your account has been created, you will get by email:
* the name of the SFTP server to connect to
* your SFTP login and password
* ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them.
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example)
# Check that your home folder contains :
#* One folder for each of the three example games (reversi, hearts, gomoku)
#* One folder matching the game you will be developing
#* One 'resources.html' file
# Open the resources.html file, it contains :
#* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file
#* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two)
#* The URL pointing to the web administration tool for the BGA Studio database.
# Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user.
== Launch your game and check how to update it ==
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
== Commit your changes ==
Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development.
Here is how to go through your first commit:
# Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared);
# Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button;
# Check the log for errors, it should end with the following lines:
Transmitting file data .
Committed revision #revision number#.
HAL says: done.
NB: you should also commit each time you make a change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do so.
== That's all! ==
Now you know about the basics of updating your game on BGA Studio and testing your changes.
For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]].
99a92d5b3f86aa127525af0e3fc76e9abca6fef9
Gamehelpstoneage
0
21
755
135
2013-04-14T18:57:40Z
Spacediver
718
/* Feed your people */
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, according to civilization cards acquired by you.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings).
Special rules for game with 2 players only:
* no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
Special rules for game with 3 players only:
* no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river.
* no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field
===Use the actions of your placed people===
Each player uses all his placed people in any order, and perform the corresponding actions:
* '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* '''field''': increase agriculture level.
* '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded).
* '''hut''': get one additional people.
* '''building card''': buy the building with resources, scoring some points.
* '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied.
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You may use tools to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...).
===Civilization card details===
Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card).
Place the mouse cursor on each card to see details in the tooltip.
Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore.
===Feed your people===
Each agriculture level automatically give you 1 food.
You must provide 1 food per person.
You may use any resource to feed your people if there is not enough food.
If you don't manage (or choose not) to feed your people by means above, you lose 10 points as a penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
Final number of points for each player is summed out of
* points earned during the game by acquiring buildings, minus food penalties,
* multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc).
* each resource that a player has on his player board scores 1 point
5921b3c6e17808ee318a02fc06ff06030a85b8f7
Gamehelplibertalia
0
105
756
737
2013-04-15T07:51:11Z
Mantra
2943
/* How to Play */
wikitext
text/x-wiki
Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies.
== '''How to Play''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Tokens are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure.
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
1db47195e1202cd4d33fe0ee8d989c0b20b42c52
Gamehelpcantstop
0
35
757
703
2013-04-17T06:10:09Z
Spheniscine
2908
wikitext
text/x-wiki
Can't Stop is a very easy and fast game!
'''How to play'''
Roll four standard dice. Divide them into two groups of two dice however you like, and advance on the appropriate track(s). You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have fewer.
'''The object of the game is''' to reach and cover 3 peaks of these columns!
f9c605bcf2b10f1518626fd7ce451fa440ce681c
Main game logic: yourgamename.game.php
0
86
758
688
2013-04-18T14:32:20Z
Pikiou
1872
/* Game states and active players */ Precision on setPlayersMultiactive
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new feException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
b9878cf2203fdcacd211b41f75d0f03be44bb80a
Tutorial reversi
0
57
759
389
2013-04-19T12:36:14Z
Garcia1968
2900
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "states.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* Server side, check the move is correct, apply Reversi rules and jump to next player.
* Client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$player_id = self::getActivePlayerId();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
To make the statistics work, we have to initialize them in state.inc.php:
<pre>
// Statistics existing for each player
"player" => array(
"discPlayedOnCorner" => array( "id"=> 10,
"name" => totranslate("Discs played on a corner"),
"type" => "int" ),
"discPlayedOnBorder" => array( "id"=> 11,
"name" => totranslate("Discs played on a border"),
"type" => "int" ),
"discPlayedOnCenter" => array( "id"=> 12,
"name" => totranslate("Discs played on board center part"),
"type" => "int" ),
"turnedOver" => array( "id"=> 13,
"name" => totranslate("Number of discs turned over"),
"type" => "int" )
)
</pre>
A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Activate next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appear automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handles the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Make these discs blink and set them to the specified color
for( var i in notif.args.turnedOver )
{
var token = notif.args.turnedOver[ i ];
// Make the token blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeOut( {
node: 'token_'+token.x+'_'+token.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'tokencolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
d0f5fd5942831d1805c5cf65817d5dfdb0bbfba6
Gamehelpgearnpiston
0
112
760
2013-04-19T13:01:05Z
Pikiou
1872
Created page with "=QUICK RULES REFERENCE= ==ROUND SEQUENCE AND PHASES== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ==LOCATION ACTIONS== *Back Alley: Choo..."
wikitext
text/x-wiki
=QUICK RULES REFERENCE=
==ROUND SEQUENCE AND PHASES==
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
==LOCATION ACTIONS==
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade.
==REQUIREMENTS OF A COMPLETE AUTOMOBILE==
* Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles.
* Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type.
* Each part on the top row requires a part on the bottom row and vice versa.
* Each Axle supports only the five parts surrounding it.
==GAME END==
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
==SCORING==
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
936ccfde729bfdf1af1090698d33ea21dacd50cd
761
760
2013-04-19T13:18:14Z
Pikiou
1872
Smaller titles
wikitext
text/x-wiki
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade.
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles.
* Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type.
* Each part on the top row requires a part on the bottom row and vice versa.
* Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
====SCORING====
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
9585ac256cef85265388481e8ff6f7409cf7dd8b
762
761
2013-04-19T13:20:28Z
Pikiou
1872
Introduction sentence
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade.
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles.
* Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type.
* Each part on the top row requires a part on the bottom row and vice versa.
* Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
====SCORING====
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
82f66c7de4d9a33ed8b6b26c761118881b4366ce
763
762
2013-04-19T21:22:24Z
Jukka h
2977
/* LOCATION ACTIONS */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles.
* Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type.
* Each part on the top row requires a part on the bottom row and vice versa.
* Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
====SCORING====
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
29595ee77bed2a188e6083d0ce260b31cc174dce
764
763
2013-04-20T12:31:19Z
Jukka h
2977
/* QUICK RULES REFERENCE */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles.
* Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type.
* Each part on the top row requires a part on the bottom row and vice versa.
* Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
====SCORING====
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action
0016c51475c81cf2ea3c5b6365bbd3fa798d1a44
765
764
2013-04-20T12:40:27Z
Jukka h
2977
/* BEGINNER TIPS */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles.
* Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type.
* Each part on the top row requires a part on the bottom row and vice versa.
* Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
====SCORING====
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
9d79b0fec2d87cb081a91d56ee045243f429fad6
776
765
2013-04-23T07:33:19Z
Lolinthedark
3013
/* LOCATION ACTIONS */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles.
* Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type.
* Each part on the top row requires a part on the bottom row and vice versa.
* Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
====SCORING====
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
350628121ba1bd4cd19bcc14ce0137a554a154d1
Scrollmap
0
110
766
736
2013-04-20T16:06:32Z
Een
3
/* How to use Scrollmap */
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area:
<pre>
/** Scrollable area **/
#map_container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
}
#map_scrollable, #map_scrollable_oversurface {
position: absolute;
top: 205px;
left: 315px;
}
#map_surface {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
cursor: move;
}
#map_footer {
text-align: center;
}
/** Move arrows **/
#movetop,#moveleft,#moveright,#movedown {
display: block;
position: absolute;
background-image: url('../../img/common/arrows.png');
width: 32px;
height: 32px;
}
#movetop {
top: 0px;
left: 50%;
background-position: 0px 32px;
}
#moveleft {
top: 50%;
left: 0px;
background-position: 32px 0px;
}
#moveright {
top: 50%;
right: 0px;
background-position: 0px 0px;
}
#movedown {
bottom: 0px;
left: 50%;
background-position: 32px 32px;
}
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
== Positioning elements on game area ==
All elements on the game are must be absolute positioned (with "top" and "left" attributes).
By default, the game area is centered on 0,0 coordinates.
9bf1328defe1d592e843c1d52e57a4fb02f03b19
767
766
2013-04-20T16:08:47Z
Een
3
/* How to use Scrollmap */
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area:
<pre>
/** Scrollable area **/
#map_container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
}
#map_scrollable, #map_scrollable_oversurface {
position: absolute;
top: 205px;
left: 315px;
}
#map_surface {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
cursor: move;
}
#map_footer {
text-align: center;
}
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
== Positioning elements on game area ==
All elements on the game are must be absolute positioned (with "top" and "left" attributes).
By default, the game area is centered on 0,0 coordinates.
8be1c95eca27e0a1f53cb9de14f88a8f439ebe46
768
767
2013-04-20T16:13:01Z
Een
3
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area:
<pre>
/** Scrollable area **/
#map_container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
}
#map_scrollable, #map_scrollable_oversurface {
position: absolute;
top: 205px;
left: 315px;
}
#map_surface {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
cursor: move;
}
#map_footer {
text-align: center;
}
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
== Positioning elements on game area ==
All elements on the game are must be absolute positioned (with "top" and "left" attributes).
By default, the game area is centered on 0,0 coordinates.
== Move arrows ==
To show move arrows around the scrollmap to enable click based navigation in addition to drag and drop, add these lines to your CSS
<pre>
/** Move arrows **/
#movetop,#moveleft,#moveright,#movedown {
display: block;
position: absolute;
background-image: url('../../img/common/arrows.png');
width: 32px;
height: 32px;
}
#movetop {
top: 0px;
left: 50%;
background-position: 0px 32px;
}
#moveleft {
top: 50%;
left: 0px;
background-position: 32px 0px;
}
#moveright {
top: 50%;
right: 0px;
background-position: 0px 0px;
}
#movedown {
bottom: 0px;
left: 50%;
background-position: 32px 32px;
}
</pre>
Then, in your javascript, define the following functions
<pre>
onMoveTop : function( evt )
{
console.log( "onMoveTop" );
evt.preventDefault();
this.scrollmap.scroll( 0, 300 );
},
onMoveLeft : function( evt )
{
console.log( "onMoveLeft" );
evt.preventDefault();
this.scrollmap.scroll( 300, 0 );
},
onMoveRight : function( evt )
{
console.log( "onMoveRight" );
evt.preventDefault();
this.scrollmap.scroll( -300, 0 );
},
onMoveDown : function( evt )
{
console.log( "onMoveDown" );
evt.preventDefault();
this.scrollmap.scroll( 0, -300 );
},
</pre>
And connect onclick events on the arrows to these functions in your javascript setup
<pre>
dojo.connect( $('movetop'), 'onclick', this, 'onMoveTop' );
dojo.connect( $('moveleft'), 'onclick', this, 'onMoveLeft' );
dojo.connect( $('moveright'), 'onclick', this, 'onMoveRight' );
dojo.connect( $('movedown'), 'onclick', this, 'onMoveDown' );
</pre>
a5779da4f4a8368a11f8c98f9602ae601684abc8
769
768
2013-04-20T16:23:55Z
Een
3
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area:
<pre>
/** Scrollable area **/
#map_container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
}
#map_scrollable, #map_scrollable_oversurface {
position: absolute;
top: 205px;
left: 315px;
}
#map_surface {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
cursor: move;
}
#map_footer {
text-align: center;
}
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
== Positioning elements on game area ==
All elements on the game are must be absolute positioned (with "top" and "left" attributes).
By default, the game area is centered on 0,0 coordinates.
== Enable move arrows ==
To show move arrows icons around the scrollmap in order to enable click based navigation in addition to drag and drop, add these lines to your CSS:
<pre>
/** Move arrows **/
#movetop,#moveleft,#moveright,#movedown {
display: block;
position: absolute;
background-image: url('../../img/common/arrows.png');
width: 32px;
height: 32px;
}
#movetop {
top: 0px;
left: 50%;
background-position: 0px 32px;
}
#moveleft {
top: 50%;
left: 0px;
background-position: 32px 0px;
}
#moveright {
top: 50%;
right: 0px;
background-position: 0px 0px;
}
#movedown {
bottom: 0px;
left: 50%;
background-position: 32px 32px;
}
</pre>
In your javascript, define the following functions:
<pre>
onMoveTop : function( evt )
{
console.log( "onMoveTop" );
evt.preventDefault();
this.scrollmap.scroll( 0, 300 );
},
onMoveLeft : function( evt )
{
console.log( "onMoveLeft" );
evt.preventDefault();
this.scrollmap.scroll( 300, 0 );
},
onMoveRight : function( evt )
{
console.log( "onMoveRight" );
evt.preventDefault();
this.scrollmap.scroll( -300, 0 );
},
onMoveDown : function( evt )
{
console.log( "onMoveDown" );
evt.preventDefault();
this.scrollmap.scroll( 0, -300 );
},
</pre>
And connect onclick events on the arrows to these functions in your javascript setup
<pre>
dojo.connect( $('movetop'), 'onclick', this, 'onMoveTop' );
dojo.connect( $('moveleft'), 'onclick', this, 'onMoveLeft' );
dojo.connect( $('moveright'), 'onclick', this, 'onMoveRight' );
dojo.connect( $('movedown'), 'onclick', this, 'onMoveDown' );
</pre>
5ab6faa990a4c4f66cd6235581c04cef32f984db
780
769
2013-04-26T13:53:16Z
Een
3
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area:
<pre>
/** Scrollable area **/
#map_container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
}
#map_scrollable, #map_scrollable_oversurface {
position: absolute;
top: 205px;
left: 315px;
}
#map_surface {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
cursor: move;
}
#map_footer {
text-align: center;
}
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
== Positioning elements on game area ==
All elements on the game are must be absolute positioned (with "top" and "left" attributes).
By default, the game area is centered on 0,0 coordinates.
== Enable move arrows ==
To show move arrows icons around the scrollmap in order to enable click based navigation in addition to drag and drop, add these lines to your CSS:
<pre>
/** Move arrows **/
#movetop,#moveleft,#moveright,#movedown {
display: block;
position: absolute;
background-image: url('../../img/common/arrows.png');
width: 32px;
height: 32px;
}
#movetop {
top: 0px;
left: 50%;
background-position: 0px 32px;
}
#moveleft {
top: 50%;
left: 0px;
background-position: 32px 0px;
}
#moveright {
top: 50%;
right: 0px;
background-position: 0px 0px;
}
#movedown {
bottom: 0px;
left: 50%;
background-position: 32px 32px;
}
</pre>
In your javascript, define the following functions:
<pre>
onMoveTop : function( evt )
{
console.log( "onMoveTop" );
evt.preventDefault();
this.scrollmap.scroll( 0, 300 );
},
onMoveLeft : function( evt )
{
console.log( "onMoveLeft" );
evt.preventDefault();
this.scrollmap.scroll( 300, 0 );
},
onMoveRight : function( evt )
{
console.log( "onMoveRight" );
evt.preventDefault();
this.scrollmap.scroll( -300, 0 );
},
onMoveDown : function( evt )
{
console.log( "onMoveDown" );
evt.preventDefault();
this.scrollmap.scroll( 0, -300 );
},
</pre>
And connect onclick events on the arrows to these functions in your javascript setup
<pre>
dojo.connect( $('movetop'), 'onclick', this, 'onMoveTop' );
dojo.connect( $('moveleft'), 'onclick', this, 'onMoveLeft' );
dojo.connect( $('moveright'), 'onclick', this, 'onMoveRight' );
dojo.connect( $('movedown'), 'onclick', this, 'onMoveDown' );
</pre>
== Enable scrollmap zone extension ==
This is optional, when there can be unused screen space under the scrollmap that a player might want to use.
Add this in your .tpl after the scrollmap div (the matching css rules has already been defined):
<pre>
<div id="map_footer" class="whiteblock">
<a href="#" id="enlargedisplay">↓ {LABEL_ENLARGE_DISPLAY} ↓</a>
</div>
</pre>
In your javascript, define the following function:
<pre>
onIncreaseDisplayHeight: function( evt )
{
console.log( '$$$$ Event : onIncreaseDisplayHeight' );
evt.preventDefault();
var cur_h = toint( dojo.style( $('map_container'), 'height' ) );
dojo.style( $('map_container'), 'height', ( cur_h+300 ) + 'px' );
},
</pre>
and connect them to the 'enlargedisplay' link in your setup:
<pre>
dojo.connect( $('enlargedisplay'), 'onclick', this, 'onIncreaseDisplayHeight' );
</pre>
2a5e97072af863315ae4bad3c5110f7b7a36fd68
781
780
2013-04-26T13:57:14Z
Een
3
/* Enable scrollmap zone extension */
wikitext
text/x-wiki
Scrollmap is a BGA client side component to display an infinite game area.
In some games, players are building the main game area with tiles or cards. Examples:
* Carcassonne
* Saboteur
* Takenoko
* Taluva
* ...
Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you.
== Scrollmap in action ==
If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress.
In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll.
== How to use Scrollmap ==
At first, don't forget to add "ebg/scrollmap" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/scrollmap" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Scrollmap object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Scrollable area
this.scrollmap = new ebg.scrollmap();
</pre>
Now, open your template (TPL) file and add this HTML code:
<pre>
<div id="map_container">
<div id="map_scrollable"></div>
<div id="map_surface"></div>
<div id="map_scrollable_oversurface"></div>
<a id="movetop" href="#"></a>
<a id="moveleft" href="#"></a>
<a id="moveright" href="#"></a>
<a id="movedown" href="#"></a>
</div>
</pre>
There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area:
<pre>
/** Scrollable area **/
#map_container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
}
#map_scrollable, #map_scrollable_oversurface {
position: absolute;
top: 205px;
left: 315px;
}
#map_surface {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
cursor: move;
}
#map_footer {
text-align: center;
}
</pre>
Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method:
<pre>
// Make map scrollable
this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') );
this.scrollmap.setupOnScreenArrows( 150 );
</pre>
This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step.
== Scrollable area layers ==
There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area:
* inside "map_scrollable" div
* inside "map_scrollable_oversurface" div
The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice:
* If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it.
* If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element.
Of course, all layers are scrolled synchronously.
Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason.
== Positioning elements on game area ==
All elements on the game are must be absolute positioned (with "top" and "left" attributes).
By default, the game area is centered on 0,0 coordinates.
== Enable move arrows ==
To show move arrows icons around the scrollmap in order to enable click based navigation in addition to drag and drop, add these lines to your CSS:
<pre>
/** Move arrows **/
#movetop,#moveleft,#moveright,#movedown {
display: block;
position: absolute;
background-image: url('../../img/common/arrows.png');
width: 32px;
height: 32px;
}
#movetop {
top: 0px;
left: 50%;
background-position: 0px 32px;
}
#moveleft {
top: 50%;
left: 0px;
background-position: 32px 0px;
}
#moveright {
top: 50%;
right: 0px;
background-position: 0px 0px;
}
#movedown {
bottom: 0px;
left: 50%;
background-position: 32px 32px;
}
</pre>
In your javascript, define the following functions:
<pre>
onMoveTop : function( evt )
{
console.log( "onMoveTop" );
evt.preventDefault();
this.scrollmap.scroll( 0, 300 );
},
onMoveLeft : function( evt )
{
console.log( "onMoveLeft" );
evt.preventDefault();
this.scrollmap.scroll( 300, 0 );
},
onMoveRight : function( evt )
{
console.log( "onMoveRight" );
evt.preventDefault();
this.scrollmap.scroll( -300, 0 );
},
onMoveDown : function( evt )
{
console.log( "onMoveDown" );
evt.preventDefault();
this.scrollmap.scroll( 0, -300 );
},
</pre>
And connect onclick events on the arrows to these functions in your javascript setup
<pre>
dojo.connect( $('movetop'), 'onclick', this, 'onMoveTop' );
dojo.connect( $('moveleft'), 'onclick', this, 'onMoveLeft' );
dojo.connect( $('moveright'), 'onclick', this, 'onMoveRight' );
dojo.connect( $('movedown'), 'onclick', this, 'onMoveDown' );
</pre>
== Enable scrollmap zone extension ==
This is optional, when there can be unused screen space under the scrollmap that a player might want to use.
Add this in your .tpl after the scrollmap div (the matching css rules has already been defined):
<pre>
<div id="map_footer" class="whiteblock">
<a href="#" id="enlargedisplay">↓ {LABEL_ENLARGE_DISPLAY} ↓</a>
</div>
</pre>
In your javascript, define the following function:
<pre>
onIncreaseDisplayHeight: function( evt )
{
console.log( '$$$$ Event : onIncreaseDisplayHeight' );
evt.preventDefault();
var cur_h = toint( dojo.style( $('map_container'), 'height' ) );
dojo.style( $('map_container'), 'height', ( cur_h+300 ) + 'px' );
},
</pre>
and connect them to the 'enlargedisplay' link in your setup:
<pre>
dojo.connect( $('enlargedisplay'), 'onclick', this, 'onIncreaseDisplayHeight' );
</pre>
In your view.php file, define the template variable LABEL_ENLARGE_DISPLAY so that it gets substituted with appropriate translatable text:
<pre>
$this->tpl['LABEL_ENLARGE_DISPLAY'] = self::_("Enlarge display");
</pre>
3589839894165d82db552742333c42b99f573a78
Zone
0
113
770
2013-04-20T17:16:41Z
Een
3
Created page with "The Zone component is meant to organise items of the same type inside a predefined space. == Zone in action == If you want to see how Zone works, please try "Can't Stop" or ..."
wikitext
text/x-wiki
The Zone component is meant to organise items of the same type inside a predefined space.
== Zone in action ==
If you want to see how Zone works, please try "Can't Stop" or "Niagara" on BGA, or watch a game in progress or game replay.
In Can't Stop, zone is used to display the bhikkus ascending the mountain when there is more than one on the same space (diagonal mode).
In Niagara, it is used to display the canoes over the circles going down the river (custom mode).
== How to use Zone ==
At first, don't forget to add "ebg/zone" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/zone" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Zone object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Zone control
this.myZone = new ebg.scrollmap();
</pre>
Now, in your template file, you must add a div that will host this zone:
<pre>
<div id="my_zone"></div>
</pre>
And set its width (and optionnaly, height and position) in CSS:
<pre>
#my_zone {
width: 100px;
}
</pre>
Then in your Javascript setup, attach your Zone component to the div and define its properties :
<pre>
zone.create( this, 'my_zone', <item_width>, <item_height> );
zone.setPattern( <mode> );
</pre>
* <item_width> is an integer for the width of the objects you want to organise in the zone
* <item_height> is an integer for the height of the objects you want to organise in the zone
* <mode> is one of 'grid' (objects will be put on lines from top left to bottom right, wrapping when there is not enough space left on the line) 'diagonal' (objects will be organised on a top left to bottom right diagonal, overlapping each other) or 'custom' (objects will be organised depending upon their number and the coordinates that you provide - see below)
3b1acb84955007d42770352ff5eaec3220ecff2f
771
770
2013-04-20T17:38:13Z
Een
3
wikitext
text/x-wiki
The Zone component is meant to organise items of the same type inside a predefined space.
== Zone in action ==
If you want to see how Zone works, please try "Can't Stop" or "Niagara" on BGA, or watch a game in progress or game replay.
In Can't Stop, zone is used to display the bhikkus ascending the mountain when there is more than one on the same space (diagonal mode).
In Niagara, it is used to display the canoes over the circles going down the river (custom mode).
== How to use Zone ==
At first, don't forget to add "ebg/zone" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/zone" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Zone object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Zone control
this.myZone = new ebg.scrollmap();
</pre>
Now, in your template file, you must add a div that will host this zone:
<pre>
<div id="my_zone"></div>
</pre>
And set its width (and optionnaly, height and position) in CSS:
<pre>
#my_zone {
width: 100px;
}
</pre>
Then in your Javascript setup, attach your Zone component to the div and define its properties :
<pre>
zone.create( this, 'my_zone', <item_width>, <item_height> );
zone.setPattern( <mode> );
</pre>
* <item_width> is an integer for the width of the objects you want to organise in the zone
* <item_height> is an integer for the height of the objects you want to organise in the zone
* <mode> is one of 'grid' (objects will be put on lines from top left to bottom right, wrapping when there is not enough space left on the line) 'diagonal' (objects will be organised on a top left to bottom right diagonal, overlapping each other) or 'custom' (objects will be organised depending upon their number and the coordinates that you provide - see below)
Now your zone is ready to be used!
After creating an object that you want to add to the zone as a classic HTML template (dojo.place / this.format_block), you can simply use:
<pre>
zone.placeInZone( <object_id>, <weight> );
</pre>
* <object_id> is the string identifier for your object 'my_object_id'
* <weight> is an optional parameter used to sort items
To remove an item, use:
<pre>
zone.removeFromZone( <object_id>, <destroy?>, <to> );
</pre>
* <object_id> is the string identifier for your object 'my_object_id'
* <destroy?> is a boolean indicating if the object should be destroyed after being removed
* <to> is the destination the object must be slided to when being removed (before being eventually destroyed)
You can also:
* remove all items from the zone (and destroy them) using zone.removeAll();
* get the number of items in your zone using zone.getItemNumber();
* get an array of the ids of all the items using zone.getAllItems();
f3e8cbbc363d78eb8dcb46bf70ffb2710985f7bb
772
771
2013-04-20T17:42:40Z
Een
3
wikitext
text/x-wiki
The Zone component is meant to organise items of the same type inside a predefined space.
== Zone in action ==
If you want to see how Zone works, please try "Can't Stop" or "Niagara" on BGA, or watch a game in progress or game replay.
In Can't Stop, zone is used to display the bhikkus ascending the mountain when there is more than one on the same space (diagonal mode).
In Niagara, it is used to display the canoes over the circles going down the river (custom mode).
== How to use Zone ==
At first, don't forget to add "ebg/zone" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/zone" /// <==== HERE
],
</pre>
Then, declare a new variable in your class for the Zone object:
<pre>
constructor: function(){
console.log('yourgame constructor');
// Zone control
this.myZone = new ebg.scrollmap();
</pre>
Now, in your template file, you must add a div that will host this zone:
<pre>
<div id="my_zone"></div>
</pre>
And set its width (and optionnaly, height and position) in CSS:
<pre>
#my_zone {
width: 100px;
}
</pre>
Then in your Javascript setup, attach your Zone component to the div and define its properties :
<pre>
zone.create( this, 'my_zone', <item_width>, <item_height> );
zone.setPattern( <mode> );
</pre>
* <item_width> is an integer for the width of the objects you want to organise in the zone
* <item_height> is an integer for the height of the objects you want to organise in the zone
* <mode> is one of 'grid' (objects will be put on lines from top left to bottom right, wrapping when there is not enough space left on the line) 'diagonal' (objects will be organised on a top left to bottom right diagonal, overlapping each other) or 'custom' (objects will be organised depending upon their number and the coordinates that you provide - see below)
Now your zone is ready to be used!
After creating an object that you want to add to the zone as a classic HTML template (dojo.place / this.format_block), you can simply use:
<pre>
zone.placeInZone( <object_id>, <weight> );
</pre>
* <object_id> is the string identifier for your object 'my_object_id'
* <weight> is an optional parameter used to sort items
To remove an item, use:
<pre>
zone.removeFromZone( <object_id>, <destroy?>, <to> );
</pre>
* <object_id> is the string identifier for your object 'my_object_id'
* <destroy?> is a boolean indicating if the object should be destroyed after being removed
* <to> is the destination the object must be slided to when being removed (before being eventually destroyed)
You can also:
* remove all items from the zone (and destroy them) using zone.removeAll();
* get the number of items in your zone using zone.getItemNumber();
* get an array of the ids of all the items using zone.getAllItems();
== Custom mode ==
If you want complete control on how your objects are laid out inside the Zone, you can determine their coordinates after their number when being added to the zone. Here is how to do it, when defining your Zone properties in the javascript setup:
<pre>
this.zone.setPattern( 'custom' );
this.zone.itemIdToCoords = function( i, control_width ) {
if( i%8==0 )
{ return { x:1,y:19, w:60, h:30 }; }
else if( i%8==1 )
{ return { x:30,y:38, w:60, h:30 }; }
else if( i%8==2 )
{ return { x:42,y:8, w:60, h:30 }; }
else if( i%8==3 )
{ return { x:5,y:58, w:60, h:30 }; }
else if( i%8==4 )
{ return { x:5,y:24, w:60, h:30 }; }
else if( i%8==5 )
{ return { x:35,y:43, w:60, h:30 }; }
else if( i%8==6 )
{ return { x:47,y:13, w:60, h:30 }; }
else if( i%8==7 )
{ return { x:10,y:63, w:60, h:30 }; }
};
</pre>
afea6db99aa0caa0117e35848e3982a5cefa003e
사용자토론:Elisha
3
114
773
2013-04-21T20:36:30Z
Elisha
2997
Camp Phillip
wikitext
text/x-wiki
== Camp Phillip ==
It is in Wautoma
7a30187f839af147b50b8b04b297d320f6416207
Tools and tips of BGA Studio
0
99
774
724
2013-04-21T21:46:57Z
Rudolf
2790
/* Run from the chat */ MoneyToPlayer instead ToCurrentPleyer
wikitext
text/x-wiki
== Starting a game in one click ==
To start a game:
* Create a new table with your game.
* If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table.
* Click on "Express Start".
== Stopping a game in one click ==
* Click on the "quit" icon on the top right of the screen.
* Click on "Express Stop".
== Switching between users ==
when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective.
== Access to game database ==
Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game.
== Save & restore state ==
Using links of this section, you can save the complete current (database) state of your game, then restore it later.
This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine.
We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations.
Limits:
* the "restore" function does not work anymore when the game is over.
* a saved situation from a given table cannot be restored in another table.
* when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually.
== Input/Output debugging section ==
This section shows you:
* The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">"
* The notifications received by your game interface. Notifications (inputs) begins with "<".
Note: if you click on some notification title, you can resend it immediately to the user interface.
== Run from the chat ==
On BGA Studio, you can directly run a PHP method from the chat.
For example, if on your PHP you have this method:
<pre>
function giveMoneyToPlayer($player_id, $amount)
{
// Do some stuff
}
</pre>
You can call this method directly from the chat like this: "giveMoneyToPlayer(2564,2)".
== Dev Tips ==
'''Edit TPL''' <p>
To edit TPL with HTML code highlightings in Gedit under Ubuntu:
find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...).
<br>
Here it's 3.0, then type in a terminal window:
<pre>
sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang
</pre>
then find 'globs' section, and change:
<pre>
<property name="globs">*.html;*.htm;*.tpl</property>
</pre>
7575406d5970f76c7920d09a72393b76aa7a139e
How to join BGA developer team?
0
83
777
740
2013-04-24T20:19:05Z
Een
3
²
wikitext
text/x-wiki
'''--- Notice ---'''
We have received a lot of positive feedback on the Studio, and lots of developers have registered.
We are very happy about it, but it comes with a cost in time spent answering emails and posts on the forum.
So please bear with us if we are slow to answer. As soon as we can, we will.
Thanks again for your interest!
Registering is done by e-mail at '''studio(at)boardgamearena.com'''.
Please provide the following information:
* your player user name on BGA
* your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character);
* your real name;
* your e-mail address;
* your postal address.
We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf ''''terms & conditions' document''']. It's very light, so as to get to the fun part faster.
To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: ''''I agree with the terms & conditions for developers on BGA Studio joined as an attachment''''.
And of course, we also encourage you to tell us about your developer experience and which games you would love to develop on BGA!
== Ok, I registered, what do I get? ==
First, we'll discuss by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum)
Second, once we have discussed together and are set on a game you'll take charge of, we'll create your studio account and you will get:
* one login / password to access files through SFTP
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
Once logged in to your SFTP root folder, you will find:
* a ''''resources.html'''' file with the URLs to use and some extra connection information
* three folders containing the three simple games provided as examples
* a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!)
Then... well that's all, you can start! See [[Studio#Great.2C_I.27m_in.21_..._How_should_I_start.3F|Great, I'm in! ... How should I start?]]
f33949896ce62ca89e3592d2b284019fa26aa725
Studio FAQ
0
53
778
582
2013-04-25T20:01:50Z
Een
3
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Should I use images free from copyright? ==
If you are developing a game in the public domain, yes (or you can make your own if you feel it's better).
If you are developing a game for which we have a licence, we will usually provide art files from the publisher.
de2963afe15123299fc130eb797b6dec2336f852
779
778
2013-04-25T20:03:11Z
Een
3
/* Should I use images free from copyright? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us.
== Should I use images free from copyright? ==
If you are developing a game in the public domain, yes (or you can make your own if you feel it's better).
If you are developing a game for which we have a licence, we will usually provide art files from the publisher.
0a29445f5efe57020b3a57c7cd1dc368e323f8a7
Gamehelpjaipur
0
115
782
2013-04-28T02:32:04Z
Coolpapa
3036
Rules summary added
wikitext
text/x-wiki
In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
- "Take" a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
- "Trade" for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards.
- "Sell" cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded.
The game continues until either:
- Three piles of goods tokens are depleted, OR
- The card row cannot be replenished.
At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.
961a44a284c0dcaf904d1e738bef062cb01b38a7
786
782
2013-04-28T22:47:55Z
Zkiller
1253
wikitext
text/x-wiki
In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
- Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
- Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards.
- Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded.
The game continues until either:
- Three piles of goods tokens are depleted, OR
- The card row cannot be replenished.
At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.
e36707fc2bb42423ae195ad7e075bda6793b9811
787
786
2013-04-28T22:48:26Z
Zkiller
1253
wikitext
text/x-wiki
In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
- Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
- Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards.
- Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded.
The game continues until either:
- Three piles of goods tokens are depleted, OR
- The card row cannot be replenished.
At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.
b784c03317aaeaa85595a08a0437840627e181f5
788
787
2013-04-28T22:48:54Z
Zkiller
1253
wikitext
text/x-wiki
In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
- Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
- Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards.
- Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded.
The game continues until either:
- Three piles of goods tokens are depleted, OR
- The card row cannot be replenished.
At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.
afbf2081c76a32ae7bfaa6e3df778a7baa8af5a4
789
788
2013-04-28T22:49:12Z
Zkiller
1253
wikitext
text/x-wiki
In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
- Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
- Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards.
- Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded.
The game continues until either:
- Three piles of goods tokens are depleted, OR
- The card row cannot be replenished.
At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.
cbe563e749c1ac4f0a52a3254a38d2a63809aa4f
790
789
2013-04-28T22:50:59Z
Zkiller
1253
wikitext
text/x-wiki
<nowiki>In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
- Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
- Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards.
- Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded.
The game continues until either:
- Three piles of goods tokens are depleted, OR
- The card row cannot be replenished.
At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.</nowiki>
dccbdb4a9810a9fbf0a6ad10688939e8cc8c6141
791
790
2013-04-28T22:51:35Z
Zkiller
1253
wikitext
text/x-wiki
In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
- Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
- Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards.
- Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded.
The game continues until either:
- Three piles of goods tokens are depleted, OR
- The card row cannot be replenished.
At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.
cbe563e749c1ac4f0a52a3254a38d2a63809aa4f
792
791
2013-04-28T22:53:13Z
Zkiller
1253
wikitext
text/x-wiki
In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
1. Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
2. Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards.
3. Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded.
The game continues until either:
Three piles of goods tokens are depleted,
OR
The card row cannot be replenished.
At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.
4252f07fcba2193fdc6fca5d3eb71abba575b82f
Gamehelpseasons
0
43
783
713
2013-04-28T08:34:30Z
Tolcso
3039
wikitext
text/x-wiki
Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
Star - increase the maximum card player can summon (max 15)
Elements - Gain an energy of the element shown (water, earth, air, fire)
Numbers - Gain the number of Crystals as indicated by the number
Square card - Draw a card
Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at)
Dots - Indicate how fast the marker progress through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund.
3ea25e6e940596dbd22fb862bd8e668ff6747768
784
783
2013-04-28T08:47:52Z
Tolcso
3039
wikitext
text/x-wiki
Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
Star - increase the maximum card player can summon (max 15)
Elements - Gain an energy of the element shown (water, earth, air, fire)
Numbers - Gain the number of Crystals as indicated by the number
Square card - Draw a card
Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at)
Dots - Indicate how fast the marker progress through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund.
Difficulty levels:
Apprentice wizard level
In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets.
Magician level
Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons.
Archmage level
All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations.
7981328360c518298628e927fdde9a7e10945645
Gamehelpthermopyles
0
116
785
2013-04-28T18:45:18Z
Boardgametravel
3042
Created page with "The rules for Thermopyles are on BoardGameTravel.com: http://boardgametravel.com/cardboard-sun-2013-thermopyles-by-touko-tahkokallio/"
wikitext
text/x-wiki
The rules for Thermopyles are on BoardGameTravel.com: http://boardgametravel.com/cardboard-sun-2013-thermopyles-by-touko-tahkokallio/
14db865c2a24bd8154124a531e44b068594fcc71
Studio
0
49
793
751
2013-04-29T13:09:31Z
Sourisdudesert
1
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio back-office]]
* [[Studio FAQ]]
== BGA Developer team organization ==
* [[Steps to create a BGA game]]
* [[Post-release phase]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
09360c43e84cfb0fda9ec982df2ba3017f8ff4a1
Steps to create a BGA game
0
117
794
2013-04-29T13:33:24Z
Sourisdudesert
1
Created page with " Here's a summary of the different steps you would follow when developing a game with BGA Studio. {| class="wikitable" |- ! Step !! How to reach this ste?p !! What happened d..."
wikitext
text/x-wiki
Here's a summary of the different steps you would follow when developing a game with BGA Studio.
{| class="wikitable"
|-
! Step !! How to reach this ste?p !! What happened during the step?
|-
| Initial || [[How to join BGA developer team?]] || You discuss with us to choose your game
|-
| Assigned || You choosed a game || You can start the development of the game
|-
| Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice.
|-
| Alpha || You tell us that your development is finished || We are reviewing the game on our side and with you, and help you to finalize some details to polish the game.
|-
| Private beta || We give a "go" || The game is incorporate in BGA global "package", and is published on BGA preproduction server. On this platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer.
|-
| Public beta || The adaptation is approved by the publiher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]].
|-
| Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]].
|}
fd83647a0d63ee8c73d0d758a652a4fa882a89e9
Post-release phase
0
118
795
2013-04-29T13:55:59Z
Sourisdudesert
1
Created page with " Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify..."
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package:
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
00719bc33fbb31e5b9d0411273ca6934503dc879
796
795
2013-04-29T13:59:21Z
Sourisdudesert
1
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
3d6fce514ac532c20726ecc2298f198752a759a4
797
796
2013-04-29T14:02:35Z
Sourisdudesert
1
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed.
06912ed7642ce5075efe6e07129b9d6f7ef509e9
798
797
2013-04-29T14:09:13Z
Sourisdudesert
1
/* What can be modified after release? */
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one BGA package, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''.
1773893f8e863b61a600264dce70ad22267ac46c
799
798
2013-04-29T14:11:38Z
Sourisdudesert
1
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== Bugs reporting ==
Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum].
During days after your game has been published and from time to time, please have a look at it to check if everything is fine.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one BGA package, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''.
* Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version.
===Major changes===
700ca998e835f73a7be0541d4dc13a951a7c837e
800
799
2013-04-29T14:14:49Z
Sourisdudesert
1
/* Major changes */
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== Bugs reporting ==
Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum].
During days after your game has been published and from time to time, please have a look at it to check if everything is fine.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one BGA package, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''.
* Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version.
===Major changes===
If you do some major changes to your game like:
* Introducing a new expansion.
* Major code rewriting/refactoring.
... please tell us. In this case, we can:
* Make your game back from "gold" to "public beta", to incite player to report bugs.
* Discuss with you about the release date of the next BGA package.
* Pay attention to your game when publishing the package.
* And eventually, publish a news about it :)
1e2c8a7c70f2e90310a06b99dbed1777b7587ac9
801
800
2013-05-02T12:01:04Z
Sourisdudesert
1
/* BGA packages: when my updates will be visible by players? */
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== Bugs reporting ==
Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum].
During days after your game has been published and from time to time, please have a look at it to check if everything is fine.
== How to submit changes? ==
To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase.
Warning: as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one BGA package, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''.
* Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version.
===Major changes===
If you do some major changes to your game like:
* Introducing a new expansion.
* Major code rewriting/refactoring.
... please tell us. In this case, we can:
* Make your game back from "gold" to "public beta", to incite player to report bugs.
* Discuss with you about the release date of the next BGA package.
* Pay attention to your game when publishing the package.
* And eventually, publish a news about it :)
a894a30459e913bc4e1ea7a84648f20439ac5bef
Post-release phase
0
118
802
801
2013-05-02T12:01:12Z
Sourisdudesert
1
/* How to submit changes? */
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== Bugs reporting ==
Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum].
During days after your game has been published and from time to time, please have a look at it to check if everything is fine.
== How to submit changes? ==
To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase.
'''Warning''': as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one BGA package, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''.
* Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version.
===Major changes===
If you do some major changes to your game like:
* Introducing a new expansion.
* Major code rewriting/refactoring.
... please tell us. In this case, we can:
* Make your game back from "gold" to "public beta", to incite player to report bugs.
* Discuss with you about the release date of the next BGA package.
* Pay attention to your game when publishing the package.
* And eventually, publish a news about it :)
3a40bfbd6133af2d943ac159671a956ff80bb408
803
802
2013-05-02T12:05:14Z
Sourisdudesert
1
/* What can be modified after release? */
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== Bugs reporting ==
Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum].
During days after your game has been published and from time to time, please have a look at it to check if everything is fine.
== How to submit changes? ==
To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase.
'''Warning''': as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one BGA package, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''.
* Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version.
===Major changes===
If you do some major changes to your game like:
* Introducing a new expansion.
* Major code rewriting/refactoring.
... please tell us. In this case, we can:
* Make your game back from "gold" to "public beta", to incite player to report bugs.
* Discuss with you about the release date of the next BGA package.
* Pay attention to your game when publishing the package.
* And eventually, publish a news about it :)
===Post-release and commit===
As said above: for games already published on BGA, we assume that your code is ready to deploy as soon as you commited your changes.
In consequence, please:
* Do not commit until you finished and tested your updates.
* Do not commit a development in progress.
* As a rule of thumb: do not commit something that will bring the game in a state that should not be seen by players.
cdf42364d5f044ab669cc89ed65e8b7284dfffd0
824
803
2013-05-13T12:18:44Z
Sourisdudesert
1
/* Changes that breaks the games in progress */
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== Bugs reporting ==
Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum].
During days after your game has been published and from time to time, please have a look at it to check if everything is fine.
== How to submit changes? ==
To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase.
'''Warning''': as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one BGA package, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''.
* Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version.
=== Updating Statistics ===
You should be careful when updating a statistics:
* If you want to add a new statistics, please refer to the paragraph above ("changes that breaks the games in progress").
* If you want to update a statistic, please update it and do not remove/create another one. Otherwise, the statistic won't keep the same ID and players will lost all the historical statistics data.
* If your game is published on BGA, please don't remove any statistics (historical data will be lost).
=== Updating string to translate ===
When you update a string that has been marked to be translatable, please keep in mind that all current translations done by the BGA community will be lost.
Consequently, when you are about to modify a string to be translated (after release), please ask you the following questions:
* Is it just an English mispelling? In this case, it is better to fix the English translation of the string than the original string to be translated.
===Major changes===
If you do some major changes to your game like:
* Introducing a new expansion.
* Major code rewriting/refactoring.
... please tell us. In this case, we can:
* Make your game back from "gold" to "public beta", to incite player to report bugs.
* Discuss with you about the release date of the next BGA package.
* Pay attention to your game when publishing the package.
* And eventually, publish a news about it :)
===Post-release and commit===
As said above: for games already published on BGA, we assume that your code is ready to deploy as soon as you commited your changes.
In consequence, please:
* Do not commit until you finished and tested your updates.
* Do not commit a development in progress.
* As a rule of thumb: do not commit something that will bring the game in a state that should not be seen by players.
6e886bcf9df1b7d39c3fbacf9c439f64bb7126b7
825
824
2013-05-13T12:21:13Z
Sourisdudesert
1
/* Updating string to translate */
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== Bugs reporting ==
Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum].
During days after your game has been published and from time to time, please have a look at it to check if everything is fine.
== How to submit changes? ==
To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase.
'''Warning''': as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress.
== BGA packages: when my updates will be visible by players? ==
BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package.
It means that your updates won't be visible by players until a new package is build and released on the website.
Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following:
* We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs.
* We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :)
* If the situation is critical, we can suspend the game from BGA waiting for the update.
Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version.
Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one BGA package, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''.
* Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version.
=== Updating Statistics ===
You should be careful when updating a statistics:
* If you want to add a new statistics, please refer to the paragraph above ("changes that breaks the games in progress").
* If you want to update a statistic, please update it and do not remove/create another one. Otherwise, the statistic won't keep the same ID and players will lost all the historical statistics data.
* If your game is published on BGA, please don't remove any statistics (historical data will be lost).
=== Updating string to be translated ===
When you update a string that has been marked to be translatable, please keep in mind that all current translations done by the BGA community will be lost.
Consequently, when you are about to modify a string to be translated (after release), please ask you the following questions:
* Is it just an English misspelling? In this case, it is better to fix the English translation of the string than the original string to be translated.
* Has the meaning of the string changed? If yes, you HAVE to change the original string in order to invalidate all translations that has been done already.
* Is there a similar string already used elsewhere in my game? In this case, you'd better use it again to enjoy immediately all translations already available.
===Major changes===
If you do some major changes to your game like:
* Introducing a new expansion.
* Major code rewriting/refactoring.
... please tell us. In this case, we can:
* Make your game back from "gold" to "public beta", to incite player to report bugs.
* Discuss with you about the release date of the next BGA package.
* Pay attention to your game when publishing the package.
* And eventually, publish a news about it :)
===Post-release and commit===
As said above: for games already published on BGA, we assume that your code is ready to deploy as soon as you commited your changes.
In consequence, please:
* Do not commit until you finished and tested your updates.
* Do not commit a development in progress.
* As a rule of thumb: do not commit something that will bring the game in a state that should not be seen by players.
356393196feb99d952606ceadf545a08b97dfa02
Your game state machine: states.inc.php
0
90
804
729
2013-05-05T21:14:19Z
Rudolf
2790
/* args */ argPlayerTurn instead argPlaceWorker :)
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"args" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn", <================================== HERE
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
</pre>
It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php):
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves()
);
}
</pre>
Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn :
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above).
Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn).
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
3812e44b110471e5e6b8940d1dd683d52a7c7946
Studio function reference
0
55
805
448
2013-05-06T17:07:55Z
Sourisdudesert
1
/* Client side (Javascript functions) */
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below.
== Server side (PHP functions) ==
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: DEPRECATED (see connectClass below)
; connectClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
e95dad6f948fc435abb59e380167b6a3cabc6080
806
805
2013-05-06T17:08:23Z
Sourisdudesert
1
/* Client side (Javascript functions) */
wikitext
text/x-wiki
This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to).
This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below.
== Server side (PHP functions) ==
== Client side (Javascript functions) ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side.
; slideToObject: function( mobile_obj, target_obj, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one
: Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo.
; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay )
: Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
; addTooltip( node, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
; addTooltipHtml( node, html, delay );
: Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay );
: Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation.
: NB: all concerned nodes must have IDs to get tooltips
; addTooltipHtmlToClass( cssClass, html, delay );
: Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
: NB: all concerned nodes must have IDs to get tooltips
; addEventToClass: function( cssClassName, eventName, functionName )
: DEPRECATED (please use connectClass below)
; connectClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
; addStyleToClass: function( cssClassName, cssProperty, propertyValue )
: Same as dojo.style(), but for all the nodes set with the specified cssClassName
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; checkAction: function( action, nomessage )
: Check if player can do the specified action by taking into account: _ current game state & _ interface locking
: return true if action is authorized
: return false and display an error message if not (display no message if nomessage is specified)
; showMessage: function( msg, type )
: Show an information message during a few seconds at the top of the page
: Type can be 'error' or 'info'
; this.scoreCtrl[ player_id ].incValue( score_delta );
: Adds score_delta (positive or negative integer) to the current score value for player
160e684dfe21df32501ea756dd20aa6dad8f0b36
Gamehelpniagara
0
119
807
2013-05-08T10:38:45Z
Drstuey
3099
Created page with "Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a pl..."
wikitext
text/x-wiki
Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a player must return either:
* five different colored gems
* four gems of the same color
* seven gems of any color
The tie break is the value of the gems - the gems closer to the waterfall have a higher value. In order the gems are:
: Gem - Color - Value
: Amethyst - Violet - 1
: Diamond - Clear - 2
: Amber - Yellow - 3
: Sapphire - Blue - 4
: Ruby - Pink - 5
Players have a set of 7 paddle cards which they play to determine the speed of their canoes and the speed of the river.
4ff0d66fb1e334b75f2b1d160b47252872bad10c
808
807
2013-05-08T10:44:52Z
Drstuey
3099
wikitext
text/x-wiki
Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a player must return either:
* five different colored gems
* four gems of the same color
* seven gems of any color
The tie break is the value of the gems - the gems closer to the waterfall have a higher value. In order the gems are:
: Gem - Color - Value
: Amethyst - Violet - 1
: Diamond - Clear - 2
: Amber - Yellow - 3
: Sapphire - Blue - 4
: Ruby - Pink - 5
Players have a set of 7 paddle cards which they play to determine the speed of their canoes and the speed of the river. All players must select the card they will play before the players then move their canoes in turn order. Once a card has been played it is not available to play again until all 7 cards have been played.
572aa6c5a9b8af31652c9722ecc4b01d8201d376
839
808
2013-05-26T07:59:53Z
Drstuey
3099
wikitext
text/x-wiki
Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a player must return either:
* five different colored gems
* four gems of the same color
* seven gems of any color
The tie break is the value of the gems - the gems closer to the waterfall have a higher value. In order the gems are:
: Gem - Color - Value
: Amethyst - Violet - 1
: Diamond - Clear - 2
: Amber - Yellow - 3
: Sapphire - Blue - 4
: Ruby - Pink - 5
Players have a set of 7 paddle cards which they play to determine the speed of their canoes and the speed of the river. All players must select the card they will play before the players then move their canoes in turn order. Once a card has been played it is not available to play again until all 7 cards have been played.
After all the players have moved their canoes the river moves causing all the canoes on the river to be swept downstream. The river moves the same number of places as the lowest value paddle card played plus or minus a modifier depending on the weather. At the beginning of the game the weather is set to 0 so there is no modification but each player also has a cloud card as part of their set of paddle cards that allows them to adjust the weather and hence make the river speed up or slow down.
The number on the paddle card determines the number of spaces that the canoe moves - it costs 2 paddle points to pick up (or offload) a gem. Thus if a player chose their 5 card they could move their canoe 5 spaces *or* they could move their canoe 3 spaces and pick up a gem (or they could offload a gem and move their canoe 3 spaces). Both canoes may be moved with the same paddle card - both canoes are moved the same amount, the paddles points are not split between the canoes.
When both canoes are out of the water only one can be launched in that turn. If both canoes are in the water they must both be moved using the full value of the paddle points - a player cannot chose not to move one canoe and must always use the full value of the paddle points. However if one of the canoes is out of the water a player may choose not to launch it. Canoes may only move upstream or downstream in a single turn - it is not permitted to change direction in the middle of the turn. However one canoe could move upstream and the second one downstream.
Players may steal gems from other canoes, but only after moving upstream and only if they finish on the same space as the other player (and only if they have an empty canoes and hence space to load the gem). Turn order is therefore crucial for stealing.
11578909bb91ae614ac1f3ad026c9b251bda1aa5
Steps to create a BGA game
0
117
809
794
2013-05-09T18:54:43Z
Sourisdudesert
1
wikitext
text/x-wiki
Here's a summary of the different steps you would follow when developing a game with BGA Studio.
{| class="wikitable"
|-
! Step !! How to reach this ste?p !! What happened during the step?
|-
| Initial || [[How to join BGA developer team?]] || You discuss with us to choose your game
|-
| Assigned || You choosed a game || You can start the development of the game
|-
| Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice.
|-
| Alpha || You tell us that your development is finished || The game is incorporate in BGA global "package", and is published on BGA preproduction server. We are reviewing the game on our side and with you, and help you to finalize some details to polish the game.
|-
| Private beta || We give a "go" || On preproduction platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer.
|-
| Public beta || The adaptation is approved by the publiher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]].
|-
| Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]].
|}
7ec2dce7dd3162238a0135745a42c2144a65ca5b
Translations
0
94
810
675
2013-05-10T19:54:03Z
Een
3
/* On client side (Javascript) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== How to not make translators crazy ;) ==
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
<pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre>
Write instead:
<pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre>
(or the equivalent "dojo.string.substitute" in Javascript)
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings.
* The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate.
* Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY".
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
'''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead.
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new feException( self::_('You must choose 3 cards'), true);
// ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
22624734ef6e061272e85bfa5c3a50f5129dd586
836
810
2013-05-21T21:36:02Z
Tilalilalou
2792
/* On server side (PHP) */
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== How to not make translators crazy ;) ==
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
<pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre>
Write instead:
<pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre>
(or the equivalent "dojo.string.substitute" in Javascript)
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings.
* The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate.
* Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY".
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
'''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead.
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new BgaUserException( self::_('You must choose 3 cards') );
// ... notice the use of BgaUserException that signals that this exception is "expected". In theory, all exception that are expected should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
febee0f3048f5cfd727355754ea4e0137867df32
Gamehelpdragonheart
0
31
811
146
2013-05-11T23:04:14Z
Sternenfee83
3127
/* Cards */
wikitext
text/x-wiki
==Summary==
Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down.
==Goal==
To have the most points by the end of the game.
==Game Start==
At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board.
==End==
The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins.
==Turns==
Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship.
==Cards==
There are nine types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what.
* ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf.
* ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board.
* ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards.
* ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress.
* ''Troll'': Placing this card allows the player to take the sorceress pile.
* ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board.
* ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent.
* ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon.
* ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn.
* ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand.
550055d41a907bf6a87ac1a5a0c8521d91f520f9
Gamehelpgearnpiston
0
112
812
776
2013-05-12T03:16:10Z
Jirikki
2655
/* REQUIREMENTS OF A COMPLETE AUTOMOBILE */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
====SCORING====
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
d635ec38db2d845cad6db71b86daa4af043eacba
813
812
2013-05-12T03:27:28Z
Jirikki
2655
/* GAME END */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
* +1 VP for each part in one largest continuous area
* -1 VP for each point of Volatility
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
de7e7b26782be0047213175f41810b1b0377928a
814
813
2013-05-12T03:41:47Z
Jirikki
2655
/* SCORING */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Plan actions.
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two of each are worth either 1, 2 or 3 based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
847321eb680103116893e558e7ce2f0a3ed8c89e
815
814
2013-05-12T03:48:02Z
Jirikki
2655
/* ROUND SEQUENCE AND PHASES */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Place action tokens.
(between I and II, you may discard ONE blueprint)
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (steal a part from another player),
**or Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two of each are worth either 1, 2 or 3 based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
8fe5b6392bbbcfaf3f233a60ad6a0113dd062127
816
815
2013-05-12T03:49:44Z
Jirikki
2655
/* LOCATION ACTIONS */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Place action tokens.
(between I and II, you may discard ONE blueprint)
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (look at one player's blueprints and take one of them),
**Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two of each are worth either 1, 2 or 3 based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
8546ba6ce30fb1fa8df1d50a9f6b5cc6ad76e451
817
816
2013-05-12T03:55:30Z
Jirikki
2655
/* SCORING */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Place action tokens.
(between I and II, you may discard ONE blueprint)
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (look at one player's blueprints and take one of them),
**Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack.
*Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
9fc3e1b36e15b47dae5af304be9c4209c53f62e1
818
817
2013-05-12T04:04:02Z
Jirikki
2655
/* LOCATION ACTIONS */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Place action tokens.
(between I and II, you may discard ONE blueprint)
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (look at one player's blueprints and take one of them),
**Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack.
*Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing.
* Make sure to build often enough so you don't end up with a full hand and unspent actions.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
* Reading the actual rules helps also.
99947660d1dd9a476d1e853fcf5db23ae7914722
819
818
2013-05-12T04:26:14Z
Jirikki
2655
/* BEGINNER TIPS */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Place action tokens.
(between I and II, you may discard ONE blueprint)
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (look at one player's blueprints and take one of them),
**Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack.
*Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed.
* Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
c24c871220e1a21fa8a444d63e17d584192eb61a
820
819
2013-05-12T04:29:04Z
Jirikki
2655
/* REQUIREMENTS OF A COMPLETE AUTOMOBILE */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Place action tokens.
(between I and II, you may discard ONE blueprint)
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (look at one player's blueprints and take one of them),
**Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack.
*Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank but there can be extra fuel tanks.
* Colored improvements require an engine of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed.
* Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
900b2c3d01813d95f9b661bee2133ac6c411da5d
821
820
2013-05-12T04:33:08Z
Jirikki
2655
/* REQUIREMENTS OF A COMPLETE AUTOMOBILE */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Place action tokens.
(between I and II, you may discard ONE blueprint)
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (look at one player's blueprints and take one of them),
**Union Muscle (move Action Token ahead or behind in a location).
*Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack.
*Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank but there can be extra fuel tanks.
* Colored improvements and fuel require an motor of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed.
* Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
8941f1d92c3e211c3ee931038e0e8f7762e2cff5
822
821
2013-05-12T04:36:44Z
Jirikki
2655
/* LOCATION ACTIONS */
wikitext
text/x-wiki
It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter].
===QUICK RULES REFERENCE===
====ROUND SEQUENCE AND PHASES====
*I. Place action tokens.
(between I and II, you may discard ONE blueprint)
*II. Resolve actions.
*III. Refresh Patent Office and Junk Yard.
====LOCATION ACTIONS====
*Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase.
**Black Market (draw 3 New Parts and keep 1),
**Espionage (look at one player's blueprints and take one of them),
**Union Muscle (move an Action Token ahead in another location).
*Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack.
*Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen.
*Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round)
====REQUIREMENTS OF A COMPLETE AUTOMOBILE====
* Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism.
* Every motor requires a matching fuel tank but there can be extra fuel tanks.
* Colored improvements and fuel require an motor of same color.
* Each part on the top row requires a part on the bottom row and vice versa.
* All parts must be supported by an axle. Each Axle supports only the five parts surrounding it.
====GAME END====
*There are not enough tiles to refill a location from the refill Stack.
OR
*One of the players has a complete automobile with at least twelve parts on it.
At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up.
====SCORING====
* VP according to Investors
The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference.
* +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color.
* -1 VP for each point of Volatility not countered by a wrench icon.
====BEGINNER TIPS====
* Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed.
* Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car.
* It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office.
* The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster.
* Remember that you can upgrade multiple junk parts with one workshop action.
96babae1589a1d46b75e44846654f7ff78eb3124
토론:Gamehelpgearnpiston
1
120
823
2013-05-12T04:39:59Z
Jirikki
2655
Created page with "When using union muscle, are you swapping your token with another or are you sliding all the other tokens down when you move. Is there any reason to move your token down unles..."
wikitext
text/x-wiki
When using union muscle, are you swapping your token with another or are you sliding all the other tokens down when you move. Is there any reason to move your token down unless you are trying to throw the game to another player?
f863575cf8f5ead7a658701c4c549caeadd532e0
Gamehelpnorthwestpassage
0
121
826
2013-05-13T16:48:33Z
Tirix
1962
Early version
wikitext
text/x-wiki
'''''Looking for the Franklin Expedition'''''
''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.''
----
In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner.
== GAME CYCLE ==
The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea.
During one round, player will take up to 7 actions, in turn.
Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled.
On the player board,
:Ship: 1/2 - Sled: 3/5
means for example that there are two crewmen on the ship and five on the sled, and that one crewman is available (out of two) on the ship, and three crewmen (out of five) are available on the sled.
At the end of the round, all used Crewmen move back to «Available».
The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board.
== ACTIONS ==
=== Draw a tile ===
''Cost: 1 Crewman''
<Click on the chosen tile at the top of the board.>
The player chooses either :
* ONE large exploration tiles, chosen from the four available.
* ONE small exploration tile, chosen from among the six available.
<br/>
=== Refresh tiles and Draw ===
''Cost: 2 Crewmen''
<Click on the "Renew deck" icon.>
The player MUST:
# Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve.
# Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve.
<br/>
=== Place a tile ===
''Cost: 1 Crewman''
<Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.>
The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions:
* The tile must be placed in line with the black grid on the board.
* The tile must be placed so that at least one side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action).
* The land and sea areas of the newly-placed tile must correspond with all land and sea tiles of adjacent tiles (both orthogonally and diagonally).
If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space.
An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island.
<br/>
=== Transfer Crew ===
''Cost: 1 Crewman''
<br/>
=== Movement ===
''Cost: 1 Crewman''
<Click on the ship or sled, then on its destination.>
'''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage.
'''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen.
Multiple Ships and Sleds can be on the same tile.
A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it.
<br/>
=== Explore a Franklin site or a Strait ===
''Cost: 3 Crewmen''
<Click on the ship or sled, then on its destination.>
<br/>
=== Discover an Inuit or a Cairn ===
''Cost: 2 Crewmen''
<Click on the ship or sled, then on its destination.>
<br/>
=== Pass ===
A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round.
If a player has no available Crewmen, he automatically passes.
== END OF THE GAME ==
The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland.
In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way.
==== Exploration Points: ====
Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring).
==== Set Points: ====
Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points.
==== Abandonment Penalty: ====
Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it.
Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points.
ecefa553b528f8319a04ef171f9621b6defd20ce
838
826
2013-05-25T11:12:01Z
Tirix
1962
Completed action description
wikitext
text/x-wiki
'''''Looking for the Franklin Expedition'''''
''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.''
----
In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner.
== GAME CYCLE ==
The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea.
During one round, player will take up to 7 actions, in turn.
Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled.
At the end of the round, all used Crewmen move back to «Available».
The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board.
== ACTIONS ==
=== Draw a tile ===
''Cost: 1 Crewman''
<Click on the chosen tile at the top of the board.>
<br/>
=== Refresh tiles and Draw ===
''Cost: 2 Crewmen''
<Click on the "Renew deck" icon.>
The player MUST:
# Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve.
# Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve.
<br/>
=== Place a tile ===
''Cost: 1 Crewman''
<Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.>
The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions:
* The tile must be placed in line with the black grid on the board.
* The tile must be placed so that at least one side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action).
* The land and sea areas of the newly-placed tile must correspond with all land and sea tiles of adjacent tiles (both orthogonally and diagonally).
If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space.
An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island.
<br/>
=== Transfer Crew ===
''Cost: 1 Crewman''
<Click on the back arrows on the player board>
Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred.
<br/>
=== Movement ===
''Cost: 1 Crewman''
<Click on the ship or sled, then on its destination.>
'''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage.
'''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen.
Multiple Ships and Sleds can be on the same tile.
A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it.
<br/>
=== Explore a Franklin site or a Strait ===
''Cost: 3 Crewmen''
<Click on the bonus chip.>
1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip).
<br/>
=== Discover an Inuit or a Cairn ===
''Cost: 2 Crewmen''
<Click on the bonus chip.>
2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3).
<br/>
=== Pass ===
A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round.
If a player has no available Crewmen, he automatically passes.
== END OF THE GAME ==
The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland.
In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way.
==== Exploration Points: ====
Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring).
==== Set Points: ====
Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points.
==== Abandonment Penalty: ====
Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it.
Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points.
e58f433c9bf6661de75716fd7b6096bdece65030
Gamehelpstoneage
0
21
827
755
2013-05-16T02:09:26Z
Mexiwithacan
3157
/* Place your people on the game board */ Replaced explanation of rule changes for 2- and 3-player games with what's in the official rulebook, verbatim
wikitext
text/x-wiki
== Goal ==
Get the most victory points at the end of the game. You win some points:
* during the game, by acquiring buildings.
* at the end of the game, according to civilization cards acquired by you.
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players place their people on the game board.
2. The players use the actions of their placed people.
3. The players feed their people.
===Place your people on the game board===
Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings).
====Special considerations when playing with fewer than 4 people====
With '''3 or 2 players''', only 2 of the 3 places: tool maker, hut, and field may be filled in each round. The third place remains empty. Naturally, the empty place can be different in each round.
With '''3 players''': on each of the places: forest, clay pit, quarry, and river only 2 players may place people in each round.
With '''2 players''': on each of the places: forest, clay pit, quarry, and river only 1 player may place people in each round.
All remaining rules remain unchanged.
===Use the actions of your placed people===
Each player uses all his placed people in any order, and perform the corresponding actions:
* '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river).
* '''field''': increase agriculture level.
* '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded).
* '''hut''': get one additional people.
* '''building card''': buy the building with resources, scoring some points.
* '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied.
===Resources===
hunting grounds, forest, clay pit, quarry, and river:
Roll 1 dice per people and take corresponding resources:
* 1 food for each full 2 on hunting grounds,
* 1 wood for each full 3 on forest,
* 1 brick for each full 4 on clay pit,
* 1 stone for each full 5 on quarry,
* 1 gold for each full 6 on river.
You may use tools to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the building and receive points.
If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...).
===Civilization card details===
Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card).
Place the mouse cursor on each card to see details in the tooltip.
Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore.
===Feed your people===
Each agriculture level automatically give you 1 food.
You must provide 1 food per person.
You may use any resource to feed your people if there is not enough food.
If you don't manage (or choose not) to feed your people by means above, you lose 10 points as a penalty.
===Game end===
The game ends when:
* there are no more civilization cards at the beginning of a round
* one building stack is empty at the end of a round
Final number of points for each player is summed out of
* points earned during the game by acquiring buildings, minus food penalties,
* multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc).
* each resource that a player has on his player board scores 1 point
892f6c221390ffc0b9cef0a00215b3530435ca93
Practical debugging
0
100
828
660
2013-05-19T19:32:34Z
Een
3
/* Debugging my PHP game logic (or my view) */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
=== Add traces to your code ===
You can use the following functions in your game to add server side logging:
'''self::debug( $message )'''
'''self::trace( $message )'''
'''self::warn( $message )'''
'''self::error( $message )'''
To see the logs, you should check the "Current table error log" in the [[Studio_back-office|Studio backoffice]].
This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point.
Only the error log level will appear in production. This level should be used only for critical problems.
Other levels will show only in the development environment and can be used as you see fit.
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
As these functions are not consequences of a user action, there is no current player defined.
As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
=== when refreshing the web page, the interface remains on "Application loading..." ===
In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load.
To find this error, check if there is an error message in the Javascript console (F12).
If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition.
=== When I do a move, I got "Move recorded, waiting for update ..." forever ===
"Move recorded" means that your ajaxcall request has been sent to the server and returned normally.
"Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did.
If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code.
=== Some player action is triggered randomly when I click somewhere on the game area ===
You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area.
Most of the time it happens in this situation, when my_object element does not exists:
<pre>
dojo.connect( $("my_object"), "onclick", this, function() {
...
}
</pre>
To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not.
=== Javascript does not know how to sum two numbers ===
Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers.
As a result:
<pre>
var i=1;
i += notif.args.increment; // With notif.args.increment='1'
alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings !
</pre>
To solve this, you should use the "toint" function:
<pre>
var i=1;
i += toint( notif.args.increment ); // With notif.args.increment='1'
alert( i ); // i=2 :)
</pre>
=== Javascript: do not use substr with negative numbers ===
To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE:
<pre>
var three_last_characters = string.substr( -3 ); // Wrong
var three_last_characters = string.slice( -3 ); // Correct
</pre>
750417058c1bb321927449e3554900012f94de24
829
828
2013-05-19T20:14:01Z
Een
3
/* Add traces to your code */
wikitext
text/x-wiki
This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== Tools ==
To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.
You can save up to 3 different states.
== Debugging my game when it cannot start ==
If your game don't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
== Debugging my PHP game logic (or my view) ==
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
Example:
<pre>
// (...my code to debug)
var_dump( $my_variable );
die('ok');
// (...my code to debug)
</pre>
=== Add traces to your code ===
You can use the following functions in your game to add server side logging:
'''self::debug( $message );''' // debug level logging
'''self::trace( $message );''' // info level logging
'''self::warn( $message );''' // warning level logging
'''self::error( $message );''' // error level logging
To see the logs, you should check the "Current table error log" in the [[Studio_back-office|Studio backoffice]].
This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point.
Only the error log level will appear in production. This level should be used only for critical problems.
Other levels will show only in the development environment and can be used as you see fit.
== Debugging my HTML/CSS layout ==
Situation examples:
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?
A first useful tip when an element does not show up in the interface is to give it a red background:
<pre>
#my_element {
... some CSS definitions ...
background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything else.
Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Using Chrome "Elements" tab (thre first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Note: check Reversi example for this.
=== Add traces in your code ===
You can use the following:
'''console.log( variable_to_inspect )'''
It will give you the object structure of the variable in the Javascript console, without blocking the execution.
It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.
'''alert( variable_to_inspect )'''
It will popup what you wish and pause the execution until you click ok.
This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
== Some frequent errors ==
=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
As these functions are not consequences of a user action, there is no current player defined.
As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
=== when refreshing the web page, the interface remains on "Application loading..." ===
In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load.
To find this error, check if there is an error message in the Javascript console (F12).
If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition.
=== When I do a move, I got "Move recorded, waiting for update ..." forever ===
"Move recorded" means that your ajaxcall request has been sent to the server and returned normally.
"Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did.
If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code.
=== Some player action is triggered randomly when I click somewhere on the game area ===
You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area.
Most of the time it happens in this situation, when my_object element does not exists:
<pre>
dojo.connect( $("my_object"), "onclick", this, function() {
...
}
</pre>
To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not.
=== Javascript does not know how to sum two numbers ===
Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers.
As a result:
<pre>
var i=1;
i += notif.args.increment; // With notif.args.increment='1'
alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings !
</pre>
To solve this, you should use the "toint" function:
<pre>
var i=1;
i += toint( notif.args.increment ); // With notif.args.increment='1'
alert( i ); // i=2 :)
</pre>
=== Javascript: do not use substr with negative numbers ===
To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE:
<pre>
var three_last_characters = string.substr( -3 ); // Wrong
var three_last_characters = string.slice( -3 ); // Correct
</pre>
ac98a8a9b9102f90c29db809630e8f484835d624
Gamehelphearts
0
52
830
726
2013-05-20T13:03:03Z
Sourisdudesert
1
wikitext
text/x-wiki
Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack.
'''Rank'''
A (high) to 2 (low).
'''Setup'''
The entire deck is dealt, giving you a hand of 13 cards. After looking at your hand, choose three cards to pass to another player.
The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player across the table, (3rd hand) to the player on your right, (4th hand) no passing. The rotation repeats until the game ends.
'''Tricks'''
After passing cards, the player holding the 2 of clubs leads the first trick.
Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs.
The highest card of the suit led wins the trick. The winner of a trick starts the next trick.
Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.]
There is no trump suit.
'''Scoring'''
At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13.
If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as "shooting the moon", or "slam"), that player scores 0 and all other players score -26. Warning other players about an attempt to shoot the moon is team play, and a breach of Hearts etiquette.
When one or more players reach zero, the game ends. The player with the highest score wins.
'''Variants'''
Normal game is 100 points.
Quick game is 75 points.
30e89bee40751176339d12f280b2f8d9cb48a3ca
Studio FAQ
0
53
831
779
2013-05-20T13:04:57Z
Sourisdudesert
1
/* I added some game options / some game statistics, but they don't show? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I can't access the Studio back-office, I get a 'Not authorized' error message? ==
You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
When you modify these 2 files, you need to deploy the update from your BGA backoffice page.
== Should I use images free from copyright? ==
If you are developing a game in the public domain, yes (or you can make your own if you feel it's better).
If you are developing a game for which we have a licence, we will usually provide art files from the publisher.
c45f3903b02b0d17a05cfa31d8138ad13de036b2
Game interface stylesheet: yourgamename.css
0
96
832
683
2013-05-20T13:14:58Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the CSS stylesheet of your game User Interface.
Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript.
Usually, you are using CSS to:
1°) define the overall layout of your game
(ex: place the board on the top left, place player's hand beside, place the deck on the right, ...).
2°) create your CSS-sprites:
All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly.
Example:
<pre>
Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image):
.white_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: 0px 0px;
}
.black_token {
background-image: url('../../img/emptygame/tokens.png');
background-position: -20px 0px;
}
.token {
width: 20px;
height: 20px;
background-repeat: none;
}
</pre>
3°) ... anything else:
It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query).
This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily.
Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary.
Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them.
== Warning: using Z-index ==
You may use z-index CSS property in your game interface, but you should pay attention to the following: BGA dialogs are displayed with a z-index of 950. If you want to use z-index safely, you should use value '''lower than 900'''.
About z-index: don't forget that if you are using a z-index, your element will be displayed above all elements that do not have a z-index. So it's no use to have big z-index values: 1 is enough most of the time :)
== spectatorMode ==
When a spectator (= a player that is not part of the game) is viewing a game, the BGA framework add the CSS class "spectatorMode" to the wrapping HTML tag of your game.
This way, if you want to apply a special style to some elements of your game for spectators, you can do this in your CSS:
<pre>
.spectatorMode #your_element_id {
/* your special style */
}
</pre>
The most common usage of this is to hide some elements to spectators. For example, to hide "my hand" elements:
<pre>
.spectatorMode #my_hand {
display: none;
}
</pre>
1a49ab7082c77d4a53a5d5ceb8de2e5022b7c059
Game interface logic: yourgamename.js
0
88
833
728
2013-05-20T19:18:50Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "AnimateProperty". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
8cd1006ed8d671520c0a8a0a1280dad598241c58
834
833
2013-05-20T19:23:38Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
dd34a1edd72c4ec2e3ea05e293be06a58723bd1c
Main game logic: yourgamename.game.php
0
86
835
758
2013-05-21T16:24:52Z
Tilalilalou
2792
/* Zombie mode */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaSystemVisibleException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new BgaSystemVisibleException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
d1eb49ba1db74c83e8b9894d730fff16f76acca5
837
835
2013-05-22T09:01:51Z
Sourisdudesert
1
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this:
<pre>
$this->tie_breaker_description = self::_("Describe here your tie breaker formula");
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaVisibleSystemException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
558ac70cea14f3ea2d2f6a5577f79daacfd7ca0e
Gamehelpyatzy
0
122
840
2013-05-28T02:42:36Z
Ryanmc
3227
Created page with "Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make a dive game even more luck based...."
wikitext
text/x-wiki
Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make a dive game even more luck based.
The rules for 3 of a kind, 4 of a kind, small straight, and large straight are all different.
b651128ff941751e18c98776abb1b7d9f81e2da6
841
840
2013-05-28T02:44:47Z
Ryanmc
3227
wikitext
text/x-wiki
Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make a dive game even more luck based.
The rules for 3 of a kind, 4 of a kind, small straight, and large straight are all different.
In this implementation 3 and 4 of a kind only counts the dice used in the pairing, not the other dice.
The small straight is completely different, rather than being a 4 long straight it is explicitly a straight of 1 - 2 - 3 - 4 - 5.
The large straight is only a straight of 2 - 3 - 4 - 5 - 6.
This makes the odds identical for both straights, but has the large still worth more points.
5a33aea3e935344464ef886108e982d0a91b4b81
842
841
2013-05-28T02:45:38Z
Ryanmc
3227
wikitext
text/x-wiki
Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make the game much more random and luck-based.
The rules for 3 of a kind, 4 of a kind, small straight, and large straight are all different.
In this implementation 3 and 4 of a kind only counts the dice used in the pairing, not the other dice.
The small straight is completely different, rather than being a 4 long straight it is explicitly a straight of 1 - 2 - 3 - 4 - 5.
The large straight is only a straight of 2 - 3 - 4 - 5 - 6.
This makes the odds identical for both straights, but has the large still worth more points.
24726458c99dbf8c7b6939aa0d6508a2b49bc5de
Gamehelpraceforthegalaxy
0
41
843
193
2013-05-28T12:28:48Z
Sternenfee83
3127
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
7adcc6f45854f68b93b0161eeb54cf8e91ce7e8d
Gamehelpseasons
0
43
844
784
2013-05-28T12:34:12Z
Sternenfee83
3127
wikitext
text/x-wiki
Season is a game of generating points (crystals) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
''Star'' - increase the maximum card player can summon (max 15)
''Elements'' - Gain an energy of the element shown (water, earth, air, fire)
''Numbers'' - Gain the number of Crystals as indicated by the number
''Square card'' - Draw a card
''Dice with frames surrounding'' - Allow user to transmute energy into crystal (depend on which part of the game is at)
''Dots'' - Indicate how fast the marker progresses through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There are 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund.
== Difficulty levels: ==
'''Apprentice wizard level'''
In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets.
'''Magician level'''
Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons.
'''Archmage level'''
All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations.
4601b4113946cbb3689946db68fb320b36bf1241
Moderationpolicy
0
123
845
2013-05-30T09:10:34Z
Sourisdudesert
1
Created page with "fff"
wikitext
text/x-wiki
fff
f6949a8c7d5b90b4a698660bbfb9431503fbb995
846
845
2013-05-30T09:16:56Z
Sourisdudesert
1
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
3ee8f8ae18afb549b01482b3d46240a70c77286b
847
846
2013-05-30T09:18:38Z
Sourisdudesert
1
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
|
! scope="col" | Titre col. A
! scope="col" | Titre col. B
! scope="col" | Titre col. C
|-
! scope="row" | Titre ligne 1
| Donnée 1A
| Donnée 1B
| Donnée 1C
|-
! scope="row" | Titre ligne 2
| Donnée 2A
| Donnée 2B
| Donnée 2C
|-
! scope="row" | Titre ligne 3
| Donnée 3A
| Donnée 3B
| Donnée 3C
|}
6ae857612b37650f114fa721c3a5a5abdb5018d1
848
847
2013-05-30T09:19:59Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
|
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! scope="row" | Titre ligne 1
| Donnée 1A
| Donnée 1B
| Donnée 1C
|-
! scope="row" | Titre ligne 2
| Donnée 2A
| Donnée 2B
| Donnée 2C
|-
! scope="row" | Titre ligne 3
| Donnée 3A
| Donnée 3B
| Donnée 3C
|}
4991abca78b6669759c1e7fe1371aed63e559cf9
849
848
2013-05-30T09:28:47Z
Sourisdudesert
1
/* General rules */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
|
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! scope="row" | Titre ligne 1
| Donnée 1A
| Donnée 1B
| Donnée 1C
|-
! scope="row" | Titre ligne 2
| Donnée 2A
| Donnée 2B
| Donnée 2C
|-
! scope="row" | Titre ligne 3
| Donnée 3A
| Donnée 3B
| Donnée 3C
|}
5a0d60aab93a8b90f81fc71a8328364d7efa13fe
850
849
2013-05-30T09:29:32Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
|
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Donnée 1A
| Donnée 1A
| Donnée 1B
| Donnée 1C
|-
! Donnée 1A
| Donnée 2A
| Donnée 2B
| Donnée 2C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|}
4d8038cf38fb161ac98f3a025e4eb5033f147b0a
851
850
2013-05-30T09:38:11Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|}
87a132a31b14d541809b5f0cd1b8aa4789750a37
Moderationpolicy
0
123
852
851
2013-05-30T09:42:40Z
Sourisdudesert
1
/* General rules */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|}
65b38ed4d46b022c0ccce6a65ce099891e091650
853
852
2013-05-30T09:51:19Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
0ac9b3ec502c18ff1f45e58dc2c3742c587bf1ae
854
853
2013-05-30T09:59:42Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
934bd58f5f40ff95414519ec5ada22b98e0f1d14
855
854
2013-05-30T10:05:16Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
1b3b4318420c869b396c0be9c3512ff35afe50c9
856
855
2013-05-30T10:07:32Z
Sourisdudesert
1
/* Player profile influence */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
9043dcf975efceb574d1aa72e2526aa26923bc53
857
856
2013-05-30T10:14:21Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
7d97e2d01a1118a2f9a09532db522f4f273317c3
858
857
2013-05-30T10:20:40Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset will be done.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
652fc40f9ec94d9d3fb458ab0f9ae63380d39ece
859
858
2013-05-30T10:21:14Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
1868411fd8423695a638e416421d3aa1ed75f6b7
860
859
2013-05-30T10:25:54Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game.
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
22cd9d141acbe98da1c8d1bc8baf7fc89b6f1515
861
860
2013-05-30T10:34:18Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
! Donnée 1A
| Donnée 3A
| Donnée 3B
| Donnée 3C
|-
|}
e68acba7624471111338d95c073aa8a7a69a368b
862
861
2013-05-30T10:39:38Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
_ the player has been reported several time for the same type of case.
_ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
_ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Tranlation stealing / vandalism
| The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
6a2e94ac4dd960b596e6862a25383fe59427855e
863
862
2013-05-30T18:44:30Z
Een
3
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
* the player has been reported several time for the same type of case.
* the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
* on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Tranlation stealing / vandalism
| The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
93f81aa01f96a0d3c2096e23f0690a7d548f371b
864
863
2013-05-30T18:44:44Z
Een
3
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
* the player has been reported several times for the same type of case.
* the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
* on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Tranlation stealing / vandalism
| The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
1939137892ffed5f2613689baae03d0945413f78
865
864
2013-05-30T18:52:15Z
Een
3
/* Player profile influence */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
* the player has been reported several times for the same type of case.
* the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
* on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games player.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Tranlation stealing / vandalism
| The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
68d4eabd3846dfb8f22862ab8bbdaba0c8329ab6
866
865
2013-05-30T18:52:46Z
Een
3
/* Player profile influence */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
* the player has been reported several times for the same type of case.
* the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
* on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games played.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Tranlation stealing / vandalism
| The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
564f5ed8ba30da2f5125e2ed47d86bfa6b0d0108
867
866
2013-05-30T19:13:08Z
Een
3
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
* the player has been reported several times for the same type of case.
* the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
* on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games played.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: porn, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (porn, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one noticed the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it has to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong intent to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. It is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP address, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Translation stealing / vandalism
| The player is writing inappropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their allotted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
d6bd98861dfb4fa6b1ad8b145d252c8f61df7843
Gamehelpreversi
0
124
868
2013-05-31T20:04:56Z
Elisha
2997
Created page with "[English Rules: Link][http://en.wikipedia.org/wiki/Reversi]"
wikitext
text/x-wiki
[English Rules: Link][http://en.wikipedia.org/wiki/Reversi]
245acab3bf59561ee3167722bfe3b03c5fb3d769
Gamehelpstoneage
0
21
869
827
2013-06-01T05:13:44Z
Crazyamazing
3028
Minor rules clarifications
wikitext
text/x-wiki
== Goal ==
Gain the most Victory Points by the end of the game.
There are two ways to gain points:
* Acquiring buildings during the game for either a fixed or variable amount
* Acquiring Civilization cards during the game that give extra points at the end of the game
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players take turns placing their people on the game board.
2. The players use the actions of their placed people all at once in turn order.
3. The players feed their people.
===Phase 1:===
===Place People on the Board===
In turn order, one area at a time, players place one or more of their people in the different areas of the board. Each "ring" in each area of the board can only be occupied by one person. The exception to this rule is the hunting ground which can be occupied by as many people of any color every turn.
====Special Considerations When Playing With Fewer Than 4 Players====
When playing with '''2 or 3 players''': Of the non-resource areas (Tool Maker, Hut and Field) only two may be occupied per turn. The third place remains empty until the next round when
With '''3 players''': Of the resource areas (Forest, Clay Pit, Quarry and River) only 2 players may place people in each round, even if there are additional spaces for additional people.
With '''2 players''': Of the resource areas (Forest, Clay Pit, Quarry and River) only 1 player may place people in each round, even if there are additional spaces for additional people.
All remaining rules remain unchanged when playing with fewer than 4 players.
===Phase 2:===
===Use the Actions of Your Placed People===
In turn order each player uses all of his placed people in any order. During this phase, the following actions may be used:
* '''Hunting Grounds (Food), Forest (Wood), Clay Pit (Brick), Quarry (Stone), and River (Gold)''': Roll 1 dice per person placed and acquire resources according to the number rolled (1 Food for each full 2 on Hunting Grounds, 1 Wood for each full 3 on Forest, 1 Brick for each full 4 on Clay Pit, 1 Stone for each full 5 on Quarry, 1 Gold for each full 6 on River).
* '''Field''': Placing a person in the Field increases your Agriculture Level. Each turn during the Feeding Phase, your Agriculture Level is subtracted from the amount of people you have. A higher agriculture level allows you to more easily sustain your population.
* '''Tool Maker''': Placing a person on the Tool Maker adds one new Tool to your player board. You only have 3 tools on your player board, and each subsequent person placed on the Tool Maker upgrades one of your tools to the next level.
* '''Hut''': Place two People on the Hut to gain an extra Person to place (and feed) for the rest of the game.
* '''Building Card''': Buy the building with the resources shown on the Building Card, scoring the point value shown in the top-left corner (A question mark in the top-left corner is explained below).
* '''Civilization Card''': Buy the card with a number of resources (of any kind) depending on its position in the Civilization Card Track (1 to 4 resources depicted above the card). The immediate effect of the card is applied when purchase. The bottom half of Civilization Card is used for scoring at the end of the game.
===Resources===
Hunting Grounds, Forest, Clay Pit, Quarry, and River:
Roll 1 dice per Person placed in that area and take the corresponding resources:
* 1 Food for each full 2 on Hunting Grounds,
* 1 Wood for each full 3 on Forest,
* 1 Brick for each full 4 on Clay Pit,
* 1 Stone for each full 5 on Quarry,
* 1 Gold for each full 6 on River.
You may use tools to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the Building and receive the Point Value listed in the top-left corner of the card.
''If the building cost is Not Fixed'': If there is a question mark in the corner of the card, you win points for each of the resources used to acquire this building. The values of each resource correspond to the numbers it requires when people are placed on them:
* Each Wood is worth 3 Points,
* Each Brick is worth 4 Points,
* Each Stone is worth 5 Points,
* Each Gold is worth 6 Points.
===Civilization Card Details===
Each Civilization Card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card).
Place the mouse cursor on each card to see details in the tooltip.
Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for the top half is no longer relevant.
===Phase 3:===
===Feed Your People===
Each Agriculture Level automatically counts as 1 Food during this phase.
You must provide 1 Food per Person.
In the event that you don't have enough food, you may use any resource to feed your people.
If you don't manage (or choose not) to feed your people by the means above, you lose all of your food and 10 points as a penalty.
===Game End===
The game ends when either:
* One Building Stack is empty at the end of a round
or
* There are no more Civilization Cards at the beginning of a round
The final number of points for each player is decided by the conditions below:
* Points earned during the game by acquiring Buildings, minus Food Penalties,
* Multipliers denoted at the bottom halves of Civilization Cards collected,
* Each Resource that a Player has leftover on his Player Board Scores 1 Point
f71bdd22c0cc48908fc9fedbe676b0fcd488239f
870
869
2013-06-01T05:18:15Z
Crazyamazing
3028
Header Editing
wikitext
text/x-wiki
== Goal ==
Gain the most Victory Points by the end of the game.
There are two ways to gain points:
* Acquiring buildings during the game for either a fixed or variable amount
* Acquiring Civilization cards during the game that give extra points at the end of the game
== Rules summary ==
Each round is divided into 3 phases, which are executed in the order described:
1. The players take turns placing their people on the game board.
2. The players use the actions of their placed people all at once in turn order.
3. The players feed their people.
== Phase 1: ==
===Place People on the Board===
In turn order, one area at a time, players place one or more of their people in the different areas of the board. Each "ring" in each area of the board can only be occupied by one person. The exception to this rule is the hunting ground which can be occupied by as many people of any color every turn.
====Special Considerations When Playing With Fewer Than 4 Players====
When playing with '''2 or 3 players''': Of the non-resource areas (Tool Maker, Hut and Field) only two may be occupied per turn. The third place remains empty until the next round when
With '''3 players''': Of the resource areas (Forest, Clay Pit, Quarry and River) only 2 players may place people in each round, even if there are additional spaces for additional people.
With '''2 players''': Of the resource areas (Forest, Clay Pit, Quarry and River) only 1 player may place people in each round, even if there are additional spaces for additional people.
All remaining rules remain unchanged when playing with fewer than 4 players.
== Phase 2: ==
===Use the Actions of Your Placed People===
In turn order each player uses all of his placed people in any order. During this phase, the following actions may be used:
* '''Hunting Grounds (Food), Forest (Wood), Clay Pit (Brick), Quarry (Stone), and River (Gold)''': Roll 1 dice per person placed and acquire resources according to the number rolled (1 Food for each full 2 on Hunting Grounds, 1 Wood for each full 3 on Forest, 1 Brick for each full 4 on Clay Pit, 1 Stone for each full 5 on Quarry, 1 Gold for each full 6 on River).
* '''Field''': Placing a person in the Field increases your Agriculture Level. Each turn during the Feeding Phase, your Agriculture Level is subtracted from the amount of people you have. A higher agriculture level allows you to more easily sustain your population.
* '''Tool Maker''': Placing a person on the Tool Maker adds one new Tool to your player board. You only have 3 tools on your player board, and each subsequent person placed on the Tool Maker upgrades one of your tools to the next level.
* '''Hut''': Place two People on the Hut to gain an extra Person to place (and feed) for the rest of the game.
* '''Building Card''': Buy the building with the resources shown on the Building Card, scoring the point value shown in the top-left corner (A question mark in the top-left corner is explained below).
* '''Civilization Card''': Buy the card with a number of resources (of any kind) depending on its position in the Civilization Card Track (1 to 4 resources depicted above the card). The immediate effect of the card is applied when purchase. The bottom half of Civilization Card is used for scoring at the end of the game.
===Resources===
Hunting Grounds, Forest, Clay Pit, Quarry, and River:
Roll 1 dice per Person placed in that area and take the corresponding resources:
* 1 Food for each full 2 on Hunting Grounds,
* 1 Wood for each full 3 on Forest,
* 1 Brick for each full 4 on Clay Pit,
* 1 Stone for each full 5 on Quarry,
* 1 Gold for each full 6 on River.
You may use tools to increase the dice result and take more resources.
===Buildings===
Pay the building cost to get the Building and receive the Point Value listed in the top-left corner of the card.
''If the building cost is Not Fixed'': If there is a question mark in the corner of the card, you win points for each of the resources used to acquire this building. The values of each resource correspond to the numbers it requires when people are placed on them:
* Each Wood is worth 3 Points,
* Each Brick is worth 4 Points,
* Each Stone is worth 5 Points,
* Each Gold is worth 6 Points.
===Civilization Card Details===
Each Civilization Card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card).
Place the mouse cursor on each card to see details in the tooltip.
Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for the top half is no longer relevant.
== Phase 3: ==
===Feed Your People===
Each Agriculture Level automatically counts as 1 Food during this phase.
You must provide 1 Food per Person.
In the event that you don't have enough food, you may use any resource to feed your people.
If you don't manage (or choose not) to feed your people by the means above, you lose all of your food and 10 points as a penalty.
===Game End===
The game ends when either:
* One Building Stack is empty at the end of a round
or
* There are no more Civilization Cards at the beginning of a round
The final number of points for each player is decided by the conditions below:
* Points earned during the game by acquiring Buildings, minus Food Penalties,
* Multipliers denoted at the bottom halves of Civilization Cards collected,
* Each Resource that a Player has leftover on his Player Board Scores 1 Point
bf846958420a3a6029ddf8def947fe382ed09d03
Gamehelpniagara
0
119
871
839
2013-06-01T16:45:56Z
Pejsek2
3255
better-looking gem table
wikitext
text/x-wiki
Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a player must return either:
* five different colored gems
* four gems of the same color
* seven gems of any color
The tie break is the value of the gems - the gems closer to the waterfall have a higher value. In order the gems are:
{| class="wikitable"
! align="left"| Gem
! Color
! Value
|-
|Amethyst
|Violet
|1
|-
|Diamond
|Clear
|2
|-
|Amber
|Yellow
|3
|-
|-
|Sapphire
|Blue
|4
|-
|-
|Ruby
|Pink
|5
|}
Players have a set of 7 paddle cards which they play to determine the speed of their canoes and the speed of the river. All players must select the card they will play before the players then move their canoes in turn order. Once a card has been played it is not available to play again until all 7 cards have been played.
After all the players have moved their canoes the river moves causing all the canoes on the river to be swept downstream. The river moves the same number of places as the lowest value paddle card played plus or minus a modifier depending on the weather. At the beginning of the game the weather is set to 0 so there is no modification but each player also has a cloud card as part of their set of paddle cards that allows them to adjust the weather and hence make the river speed up or slow down.
The number on the paddle card determines the number of spaces that the canoe moves - it costs 2 paddle points to pick up (or offload) a gem. Thus if a player chose their 5 card they could move their canoe 5 spaces *or* they could move their canoe 3 spaces and pick up a gem (or they could offload a gem and move their canoe 3 spaces). Both canoes may be moved with the same paddle card - both canoes are moved the same amount, the paddles points are not split between the canoes.
When both canoes are out of the water only one can be launched in that turn. If both canoes are in the water they must both be moved using the full value of the paddle points - a player cannot chose not to move one canoe and must always use the full value of the paddle points. However if one of the canoes is out of the water a player may choose not to launch it. Canoes may only move upstream or downstream in a single turn - it is not permitted to change direction in the middle of the turn. However one canoe could move upstream and the second one downstream.
Players may steal gems from other canoes, but only after moving upstream and only if they finish on the same space as the other player (and only if they have an empty canoes and hence space to load the gem). Turn order is therefore crucial for stealing.
12cc267ba3dbd74e0d23e887ffa80fc1d0f05f81
Gamehelpnorthwestpassage
0
121
872
838
2013-06-02T04:00:04Z
Tirix
1962
Mentioned additional crewman cost for addititional actions
wikitext
text/x-wiki
'''''Looking for the Franklin Expedition'''''
''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.''
----
In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner.
== GAME CYCLE ==
The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea.
During one round, player will take up to 7 actions, in turn.
Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled.
During one turn, one player can play one or more actions. However, '''all additional actions (beyond the first one) will cost one more crewman than normal'''. In order to stop playing more actions during one turn, click the blincking [End Turn] at the top of the screen.
At the end of the round, all used Crewmen move back to «Available».
The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board.
== ACTIONS ==
=== Draw a tile ===
''Cost: 1 Crewman''
<Click on the chosen tile at the top of the board.>
<br/>
=== Refresh tiles and Draw ===
''Cost: 2 Crewmen''
<Click on the "Renew deck" icon.>
The player MUST:
# Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve.
# Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve.
<br/>
=== Place a tile ===
''Cost: 1 Crewman''
<Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.>
The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions:
* The tile must be placed in line with the black grid on the board.
* The tile must be placed so that at least one side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action).
* The land and sea areas of the newly-placed tile must correspond with all land and sea tiles of adjacent tiles (both orthogonally and diagonally).
If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space.
An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island.
<br/>
=== Transfer Crew ===
''Cost: 1 Crewman''
<Click on the back arrows on the player board>
Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred.
<br/>
=== Movement ===
''Cost: 1 Crewman''
<Click on the ship or sled, then on its destination.>
'''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage.
'''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen.
Multiple Ships and Sleds can be on the same tile.
A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it.
<br/>
=== Explore a Franklin site or a Strait ===
''Cost: 3 Crewmen''
<Click on the bonus chip.>
1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip).
<br/>
=== Discover an Inuit or a Cairn ===
''Cost: 2 Crewmen''
<Click on the bonus chip.>
2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3).
<br/>
=== Pass ===
A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round.
If a player has no available Crewmen, he automatically passes.
== END OF THE GAME ==
The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland.
In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way.
==== Exploration Points: ====
Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring).
==== Set Points: ====
Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points.
==== Abandonment Penalty: ====
Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it.
Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points.
52900610215c1c81ffdb67435634a2f1d3cc2098
873
872
2013-06-02T10:38:27Z
Tirix
1962
wikitext
text/x-wiki
'''''Looking for the Franklin Expedition'''''
''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.''
----
In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner.
== GAME CYCLE ==
The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea.
During one round, player will take up to 7 actions, in turn.
Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled.
During one turn, one player can play one or more actions. However, '''all additional actions (beyond the first one) will cost one more crewman than normal'''. In order to stop playing more actions during one turn, click the blinking [End Turn] at the top of the screen.
At the end of the round, all used Crewmen move back to «Available».
The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board.
== ACTIONS ==
=== Draw a tile ===
''Cost: 1 Crewman''
<Click on the chosen tile at the top of the board.>
<br/>
=== Refresh tiles and Draw ===
''Cost: 2 Crewmen''
<Click on the "Renew deck" icon.>
The player MUST:
# Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve.
# Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve.
<br/>
=== Place a tile ===
''Cost: 1 Crewman''
<Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.>
The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions:
* The tile must be placed in line with the black grid on the board.
* The tile must be placed so that at least one side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action).
* The land and sea areas of the newly-placed tile must correspond with all land and sea tiles of adjacent tiles (both orthogonally and diagonally).
If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space.
An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island.
<br/>
=== Transfer Crew ===
''Cost: 1 Crewman''
<Click on the back arrows on the player board>
Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred.
<br/>
=== Movement ===
''Cost: 1 Crewman''
<Click on the ship or sled, then on its destination.>
'''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage.
'''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen.
Multiple Ships and Sleds can be on the same tile.
A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it.
<br/>
=== Explore a Franklin site or a Strait ===
''Cost: 3 Crewmen''
<Click on the bonus chip.>
1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip).
<br/>
=== Discover an Inuit or a Cairn ===
''Cost: 2 Crewmen''
<Click on the bonus chip.>
2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3).
<br/>
=== Pass ===
A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round.
If a player has no available Crewmen, he automatically passes.
== END OF THE GAME ==
The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland.
In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way.
==== Exploration Points: ====
Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring).
==== Set Points: ====
Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points.
==== Abandonment Penalty: ====
Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it.
Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points.
b1ae8800a8556d2ec55b52cf4109d6778adb2b76
Gamehelpquoridor
0
102
874
695
2013-06-02T21:22:24Z
Januszk0
3262
wikitext
text/x-wiki
W grze może brać udział dwóch lub czterech graczy. Plansza złożona jest z 81 kwadratów, po których poruszają się pionki reprezentujące graczy. Na początku rozgrywki pionki należy ustawić po środku przeciwległych krawędzi planszy. Celem gry jest zostaniem pierwszym graczem, który dotrze do startowego rzędu przeciwnika. Można to uczynić poruszając się o jedno pole w 4 kierunkach lub stawiając ogrodzenia uniemożliwiające przejście. W rozgrywce dwuosobowej każdy posiada 10 drewnianych płytek, a w rozgrywce czteroosobowej po 5. Gracze wykonują ruch jeden po drugim w kolejności według ruchów zegara (pierwszy gracz jest losowany). Nie wolno całkowicie zablokować przeciwnika - zawsze musi istnieć przynajmniej jedno przejście. Istnieje także zasada mówiąca o możliwości przeskoczenia pionka przeciwnika w sytuacji, gdy stoją na przeciwko siebie w sąsiadujących polach.
b2d49d0979a63aeb3a50507fff8df67ace68c411
889
874
2013-06-16T13:41:18Z
Issity
2112
Undo revision 874 by [[Special:Contributions/Januszk0|Januszk0]] ([[User talk:Januszk0|talk]]) - Polish text was placed on English page
wikitext
text/x-wiki
[http://heyjude0929.pixnet.net/blog/post/26923277-%5B%E9%81%8A%E6%88%B2%E4%BB%8B%E7%B4%B9%5D%E6%AD%A5%E6%AD%A5%E7%82%BA%E7%87%9Fquoridor]步步為營(zh)
Corridor is a 2-player game, the object of which is to move your pawn to the other side of a 9x9 board before your opponent.
You can either move your man up,down or sideways or put a fence down. Players can jump over an opponent that he is next to or jump diagonally if he is next to a fence. Players cannot jump over fences. Players can put a fence down to block an opponent, but must allow at least one path to get to his winning side.
You have only 10 fences. There is a fence counter by your name. Set traps to delay the opponent and create corridors to a winning path. You can concede the game by clicking on the square by your name and clicking "Concede...". You must have completed 50% or more of your game.
There is an optional starting "Off the Center Aisle" Variation. Players agree to play this variation. The first player moves sideways and the second player move sideways in the opposite direction. The players keep on moving sideways until they agree to stop.
81f6185c44e295d3d224159201b0b4d3a368fc64
Gamehelpdragonheart
0
31
875
811
2013-06-07T07:45:17Z
Guszty
3271
wikitext
text/x-wiki
==Summary==
Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down.
==Goal==
To have the most points by the end of the game.
==Game Start==
At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board.
==End==
The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins.
==Turns==
Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship.
==Cards==
There are nine types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what.
* ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf.
* ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board.
* ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards.
* ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress.
* ''Troll'': Placing this card allows the player to take the sorceress pile.
* ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board.
* ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent.
* ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon.
* ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the table. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn.
* ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand.
e483577692cda37d861be7c5ae5fb36d9746d21a
Club Board Game Arena
0
8
876
20
2013-06-10T20:09:36Z
Sourisdudesert
1
wikitext
text/x-wiki
==Why can't you just have a standard donation system where I can choose any money amount ?==
With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors.
==Is it mandatory to join the club ?==
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members.
==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif ==
When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif).
==What becomes of the money ?==
Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
ff7997026610fbb6d05400848cd31c5206035eea
Gamehelppylos
0
125
877
2013-06-11T07:00:32Z
Stst
2180
Created page with "'''PLAYING A GAME''' Start of the game Each player alternately, puts a ball from his reserve into any hollow which he has chosen. '''Stacking on a square''' When one or more ..."
wikitext
text/x-wiki
'''PLAYING A GAME'''
Start of the game
Each player alternately, puts a ball from his reserve into any hollow which he has chosen.
'''Stacking on a square'''
When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between:
- taking a ball from his reserve and placing it on the board,
- placing a ball from his reserve on one of the squares of balls,
- moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls.
'''Square in the player's own color'''
A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve;
He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls).
'''END OF THE GAME'''
The winner is the one who places his last ball at the top of the pyramid
'''CHILDREN’S VERSION'''
To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls.
'''VERSION FOR MATURE PLAYERS: EXTENDED'''
A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of:
- 4 balls of the same color in line on the first level,
- 3 balls of the same color in line on the second level.
A diagonal line is not an alignment. No more than two spheres can be taken back per shot.
ee24a02786352eff33532674147b377d20f947bd
878
877
2013-06-11T07:06:04Z
Stst
2180
wikitext
text/x-wiki
'''PLAYING A GAME'''
Start of the game
Each player alternately, puts a ball from his reserve into any hollow which he has chosen.
'''Stacking on a square'''
When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between:
*taking a ball from his reserve and placing it on the board,
*placing a ball from his reserve on one of the squares of balls,
*moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls.
'''Square in the player's own color'''
A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve;
He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls).
'''END OF THE GAME'''
The winner is the one who places his last ball at the top of the pyramid
'''CHILDREN’S VERSION'''
To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls.
'''VERSION FOR MATURE PLAYERS: EXTENDED'''
A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of:
*4 balls of the same color in line on the first level,
*3 balls of the same color in line on the second level.
A diagonal line is not an alignment. No more than two spheres can be taken back per shot.
299c9719ba294c06ae48d56d5b896b41cd64edee
879
878
2013-06-11T07:07:35Z
Stst
2180
wikitext
text/x-wiki
===PLAYING A GAME===
Start of the game
Each player alternately, puts a ball from his reserve into any hollow which he has chosen.
===Stacking on a square===
When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between:
*taking a ball from his reserve and placing it on the board,
*placing a ball from his reserve on one of the squares of balls,
*moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls.
===Square in the player's own color===
A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve;
He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls).
===END OF THE GAME===
The winner is the one who places his last ball at the top of the pyramid
===CHILDREN’S VERSION===
To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls.
===VERSION FOR MATURE PLAYERS: EXTENDED===
A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of:
*4 balls of the same color in line on the first level,
*3 balls of the same color in line on the second level.
A diagonal line is not an alignment. No more than two spheres can be taken back per shot.
d0e1ce0f661f3b20511133289fa4c7a15d576504
880
879
2013-06-11T07:08:18Z
Stst
2180
/* PLAYING A GAME */
wikitext
text/x-wiki
===PLAYING A GAME===
Start of the game.
Each player alternately, puts a ball from his reserve into any hollow which he has chosen.
===Stacking on a square===
When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between:
*taking a ball from his reserve and placing it on the board,
*placing a ball from his reserve on one of the squares of balls,
*moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls.
===Square in the player's own color===
A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve;
He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls).
===END OF THE GAME===
The winner is the one who places his last ball at the top of the pyramid
===CHILDREN’S VERSION===
To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls.
===VERSION FOR MATURE PLAYERS: EXTENDED===
A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of:
*4 balls of the same color in line on the first level,
*3 balls of the same color in line on the second level.
A diagonal line is not an alignment. No more than two spheres can be taken back per shot.
b47a23568de7da199140660a582cabae45f7c3b2
881
880
2013-06-11T07:09:18Z
Stst
2180
/* END OF THE GAME */
wikitext
text/x-wiki
===PLAYING A GAME===
Start of the game.
Each player alternately, puts a ball from his reserve into any hollow which he has chosen.
===Stacking on a square===
When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between:
*taking a ball from his reserve and placing it on the board,
*placing a ball from his reserve on one of the squares of balls,
*moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls.
===Square in the player's own color===
A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve;
He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls).
===END OF THE GAME===
The winner is the one who places his last ball at the top of the pyramid.
===CHILDREN’S VERSION===
To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls.
===VERSION FOR MATURE PLAYERS: EXTENDED===
A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of:
*4 balls of the same color in line on the first level,
*3 balls of the same color in line on the second level.
A diagonal line is not an alignment. No more than two spheres can be taken back per shot.
0873de88f4bad1c0ad90275ddb11bb3c4fc3bf33
882
881
2013-06-11T11:31:49Z
Stst
2180
/* VERSION FOR MATURE PLAYERS: EXTENDED */
wikitext
text/x-wiki
===PLAYING A GAME===
Start of the game.
Each player alternately, puts a ball from his reserve into any hollow which he has chosen.
===Stacking on a square===
When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between:
*taking a ball from his reserve and placing it on the board,
*placing a ball from his reserve on one of the squares of balls,
*moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls.
===Square in the player's own color===
A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve;
He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls).
===END OF THE GAME===
The winner is the one who places his last ball at the top of the pyramid.
===CHILDREN’S VERSION===
To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls.
===VERSION FOR MATURE PLAYERS: EXTENDED===
A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of:
*4 balls of the same color in line on the first level,
*3 balls of the same color in line on the second level.
A diagonal line is not an alignment. No more than two balls can be taken back per shot.
cb99b4160b207e2265cc6194e3dd4073a76c87f3
883
882
2013-06-11T20:44:47Z
Stst
2180
/* VERSION FOR MATURE PLAYERS: EXTENDED */
wikitext
text/x-wiki
===PLAYING A GAME===
Start of the game.
Each player alternately, puts a ball from his reserve into any hollow which he has chosen.
===Stacking on a square===
When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between:
*taking a ball from his reserve and placing it on the board,
*placing a ball from his reserve on one of the squares of balls,
*moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls.
===Square in the player's own color===
A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve;
He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls).
===END OF THE GAME===
The winner is the one who places his last ball at the top of the pyramid.
===CHILDREN’S VERSION===
To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls.
===VERSION FOR MATURE PLAYERS: ADVANCED===
A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of:
*4 balls of the same color in line on the first level,
*3 balls of the same color in line on the second level.
A diagonal line is not an alignment. No more than two balls can be taken back per shot.
e726a8d5e6806f118954889b3f41813310ed8709
Gamehelpunitedsquare
0
42
884
707
2013-06-12T05:36:09Z
Chaotic iak
3338
wikitext
text/x-wiki
==Goal==
The goal is to be the player who has the most squares of his color.
==Rules==
The game uses pieces of six types, where each piece is in shape of a square. The sides of each piece are colored with one of red, yellow, green, blue, so that a piece has one side for each color. Each "side" appears as a triangle.
Each player on his turn puts a square next to a square already on the board. The piece may be rotated, but not reflected. The sides coinciding with previous pieces on the board must match in color.
It's possible for a blank square to be adjacent to two sides of the same color, blocking said square from being occupied (because there is no piece that has two sides of the same color).
When a player cannot put any piece, the turn is passed. In all other cases, the player must put some piece.
Due to the appearance of a side as a triangle, matched sides form a tilted square. Each of these squares scores a point for the person holding this color.
==Ending the game==
When no more piece can be put by any player, the player with the most squares of his color wins.
== Game preferences ==
The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD].
Learning the code is easy, just take a look at the following synthesis panel:
[[File:ColorADD.jpg]]
'''HAVE A GOOD GAME!'''
941de17dad67e96ffda31089a82f4ccbdcdacc23
Gamehelpelfenland
0
126
885
2013-06-16T12:50:55Z
Een
3
Created page with "== Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. == R..."
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins.
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3.
# One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card.
# One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes.
To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
368bc2b9b805fc1e45ba2d5b8717bf20d08e1285
886
885
2013-06-16T12:52:46Z
Een
3
/* Round overview */
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins.
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3.
# One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card.
# One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes.
To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
5e2dabcee0f80719357b72ee48d9f8c5067a45fb
887
886
2013-06-16T12:57:28Z
Een
3
/* Goal of the game */
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins.
We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the counters from other players to optimise one's travels, so the more the merrier!
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3.
# One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card.
# One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes.
To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
3c9887d2684d2aa2d6260a89e25c0ee3d74738fd
888
887
2013-06-16T13:00:56Z
Een
3
/* Goal of the game */
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins.
We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier!
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3.
# One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card.
# One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes.
To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
5109a7a3a58a66f70c401dfa41eab700fceabcdf
Gamehelpyatzy
0
122
890
842
2013-06-19T05:07:45Z
Wonderer
3397
wikitext
text/x-wiki
Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make the game much more random and luck-based.
The rules for 3 of a kind, 4 of a kind, small straight, and large straight are all different.
In this implementation 3 and 4 of a kind only counts the dice used in the pairing, not the other dice.
This makes the odds identical for both straights, but has the large still worth more points.
08961c163bea1dc1e7722529d8499e07e5d63525
891
890
2013-06-19T05:11:03Z
Wonderer
3397
Blanked the page
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Studio
0
49
892
793
2013-06-20T19:19:17Z
Sourisdudesert
1
/* BGA Studio user guide */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
See announcement here:
http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio logs]]
* [[Studio back-office]]
* [[Studio FAQ]]
== BGA Developer team organization ==
* [[Steps to create a BGA game]]
* [[Post-release phase]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
b5935f96db32b7aa0f0a029e5a5011b29c677061
Studio logs
0
127
893
2013-06-20T19:19:29Z
Sourisdudesert
1
Created page with "(to be written)"
wikitext
text/x-wiki
(to be written)
a5a10fffe3d6647651bdea1a52be1345e04bd462
894
893
2013-06-20T19:58:36Z
Sourisdudesert
1
wikitext
text/x-wiki
BGA Studio logs are available directly from your game development interface.
Logs allows you to check out what happened recently on server and to debug your game.
== BGA request&SQL logs ==
On this log, you can see:
=== Your requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]].
=== Request responses ===
Example:
20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
You can recognize a response because it contains [notice]. Usually, there is one response for each request.
Let's details the beginning of the log:
* 20/06 21:50:56: the date
* [notice]
* [T403]: this is a log from table 403
* [4/mytest0]: this is use "mytest0", with id 4
* OK-0: it means that the request ended up successfully, with no exception (expected or unexpected).
* 169: this is the time taken to process the request (169ms).
* d141: this is the total Database time used to process the request (141ms).
4123c3426fa68031dd4dd97a71e1dccfe2d70d90
895
894
2013-06-20T19:58:49Z
Sourisdudesert
1
/* Request responses */
wikitext
text/x-wiki
BGA Studio logs are available directly from your game development interface.
Logs allows you to check out what happened recently on server and to debug your game.
== BGA request&SQL logs ==
On this log, you can see:
=== Your requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]].
=== Request responses ===
Example:
20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
You can recognize a response because it contains [notice]. Usually, there is one response for each request.
Let's details the beginning of the log:
* 20/06 21:50:56: the date
* [notice]
* [T403]: this is a log from table 403
* [4/mytest0]: this is use "mytest0", with id 4
* OK-0: it means that the request ended up successfully, with no exception (expected or unexpected).
* 169: this is the time taken to process the request (169ms).
* d141: this is the total Database time used to process the request (141ms).
7857032caa340af1ad58d8a4f03e59f814f40b19
896
895
2013-06-20T20:02:52Z
Sourisdudesert
1
/* BGA request&SQL logs */
wikitext
text/x-wiki
BGA Studio logs are available directly from your game development interface.
Logs allows you to check out what happened recently on server and to debug your game.
== BGA request&SQL logs ==
This log is useful:
* When you want to check what SQL requests has been built during a request.
* When you want to debug your PHP code using "self::trace"
* When you want to know why a request takes too many time.
On this log, you can see:
=== Your requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]].
=== Request responses ===
Example:
20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
You can recognize a response because it contains [notice]. Usually, there is one response for each request.
Let's details the beginning of the log:
* 20/06 21:50:56: the date
* [notice]
* [T403]: this is a log from table 403
* [4/mytest0]: this is use "mytest0", with id 4
* OK-0: it means that the request ended up successfully, with no exception (expected or unexpected).
* 169: this is the time taken to process the request (169ms).
* d141: this is the total Database time used to process the request (141ms).
=== SQL requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4'
All requests to Database are traced in this log. You can see here the time take by the request (0,26ms).
5fb44e06a4378b1bc27d1ef9de818ff079a6161f
897
896
2013-06-20T20:06:31Z
Sourisdudesert
1
/* SQL requests */
wikitext
text/x-wiki
BGA Studio logs are available directly from your game development interface.
Logs allows you to check out what happened recently on server and to debug your game.
== BGA request&SQL logs ==
This log is useful:
* When you want to check what SQL requests has been built during a request.
* When you want to debug your PHP code using "self::trace"
* When you want to know why a request takes too many time.
On this log, you can see:
=== Your requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]].
=== Request responses ===
Example:
20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
You can recognize a response because it contains [notice]. Usually, there is one response for each request.
Let's details the beginning of the log:
* 20/06 21:50:56: the date
* [notice]
* [T403]: this is a log from table 403
* [4/mytest0]: this is use "mytest0", with id 4
* OK-0: it means that the request ended up successfully, with no exception (expected or unexpected).
* 169: this is the time taken to process the request (169ms).
* d141: this is the total Database time used to process the request (141ms).
=== SQL requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4'
All requests to Database are traced in this log. You can see here the time take by the request (0,26ms).
=== Custom trace ===
You can use special PHP methods in your PHP code to left some trace in this log:
* self::trace( "your message here" ); // Display "your message here" in the log
* self::dump( "My variable", $variable_to_dump ); // Display the content of $variable_to_dump in the log
9e994b9737a804e7ab1d1bfdb69c6c00e48a06df
898
897
2013-06-20T20:07:24Z
Sourisdudesert
1
wikitext
text/x-wiki
BGA Studio logs are available directly from your game development interface.
Logs allows you to check out what happened recently on server and to debug your game.
== BGA request&SQL logs ==
This log is useful:
* When you want to check what SQL requests has been built during a request.
* When you want to debug your PHP code using "self::trace"
* When you want to know why a request takes too many time.
On this log, you can see:
=== Your requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]].
=== Request responses ===
Example:
20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
You can recognize a response because it contains [notice]. Usually, there is one response for each request.
Let's details the beginning of the log:
* 20/06 21:50:56: the date
* [notice]
* [T403]: this is a log from table 403
* [4/mytest0]: this is use "mytest0", with id 4
* OK-0: it means that the request ended up successfully, with no exception (expected or unexpected).
* 169: this is the time taken to process the request (169ms).
* d141: this is the total Database time used to process the request (141ms).
=== SQL requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4'
All requests to Database are traced in this log. You can see here the time take by the request (0,26ms).
=== Custom trace ===
You can use special PHP methods in your PHP code to left some trace in this log:
* self::trace( "your message here" ); // Display "your message here" in the log
* self::dump( "My variable", $variable_to_dump ); // Display the content of $variable_to_dump in the log
== BGA unexpected exceptions logs ==
37bc965f13f59e5a37e9b60206ed34bc5ab9d53b
899
898
2013-06-20T20:10:01Z
Sourisdudesert
1
/* BGA unexpected exceptions logs */
wikitext
text/x-wiki
BGA Studio logs are available directly from your game development interface.
Logs allows you to check out what happened recently on server and to debug your game.
== BGA request&SQL logs ==
This log is useful:
* When you want to check what SQL requests has been built during a request.
* When you want to debug your PHP code using "self::trace"
* When you want to know why a request takes too many time.
On this log, you can see:
=== Your requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]].
=== Request responses ===
Example:
20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044
You can recognize a response because it contains [notice]. Usually, there is one response for each request.
Let's details the beginning of the log:
* 20/06 21:50:56: the date
* [notice]
* [T403]: this is a log from table 403
* [4/mytest0]: this is use "mytest0", with id 4
* OK-0: it means that the request ended up successfully, with no exception (expected or unexpected).
* 169: this is the time taken to process the request (169ms).
* d141: this is the total Database time used to process the request (141ms).
=== SQL requests ===
Example:
20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4'
All requests to Database are traced in this log. You can see here the time take by the request (0,26ms).
=== Custom trace ===
You can use special PHP methods in your PHP code to left some trace in this log:
* self::trace( "your message here" ); // Display "your message here" in the log
* self::dump( "My variable", $variable_to_dump ); // Display the content of $variable_to_dump in the log
== BGA unexpected exceptions logs ==
In this log you can check the last Unexpected exceptions from your game.
Exceptions management on PHP side [[http://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Managing_errors_and_exceptions is described here]].
The log displayed the complete stacktrace of the exception, so you can debug it.
b302ba731048fb2cebae26604f24b8d7f1941057
Gamehelpseasons
0
43
900
844
2013-06-22T20:25:45Z
Charlow
3423
wikitext
text/x-wiki
Seasons is a game of generating points (crystals) by choosing the correct combination of dice and the activation of card powers.
The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle.
Each player can choose only one die per turn.
The effects are as follows:
''Star'' - increase the maximum card player can summon (max 15)
''Elements'' - Gain an energy of the element shown (water, earth, air, fire)
''Numbers'' - Gain the number of Crystals as indicated by the number
''Square card'' - Draw a card
''Dice with frames surrounding'' - Allow user to transmute energy into crystal (depend on which part of the game is at)
''Dots'' - Indicate how fast the marker progresses through the seasons cycle
There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There are 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice).
At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins.
Note:
Users need to discard energy immediately if the energy is more than the slots allocated.
If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund.
== Difficulty levels: ==
'''Apprentice wizard level'''
In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets.
'''Magician level'''
Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons.
'''Archmage level'''
All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations.
5a76f838e4388603a11a1166cb6bacfaecc16b97
Game interface logic: yourgamename.js
0
88
901
834
2013-06-30T13:34:16Z
Een
3
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board" ).play();
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
f6a8e63abe8a7466d9a3479fed629a109b8456ee
Game interface logic: yourgamename.js
0
88
902
901
2013-06-30T13:35:10Z
Een
3
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ).play();
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
33ef921054092140ab755e1a5f8911af4ec21d61
Gamehelpelfenland
0
126
903
888
2013-07-06T22:29:06Z
Spacediver
718
/* Goal of the game */
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having equal number of Town Pieces are ranked by remaining cards (the more the better).
We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier!
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3.
# One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card.
# One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes.
To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
a06379653e76e9da044516d6027676e8ace27ccb
924
903
2013-08-18T05:23:21Z
Chazm
3718
/* Goal of the game */
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having an equal number of Town Pieces are ranked by remaining cards (the more the better).
We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier!
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3.
# One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card.
# One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes.
To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
52928b7fae91e13764e651d3e3c77b390c33e891
925
924
2013-08-18T05:33:30Z
Chazm
3718
/* Round overview */
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having an equal number of Town Pieces are ranked by remaining cards (the more the better).
We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier!
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or draws from the facedown stack, until each player has taken 3.
# One after another, each player must plan a travel route by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to increase the cost of travel by an addtional card.
# One after another, each player travels from town to town. The current position of a player is indicated by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes.
To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
604d9ffb19ecc5618c7a2ad55816fe5a2cc215f1
926
925
2013-08-18T05:37:14Z
Chazm
3718
/* Travel rules */
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having an equal number of Town Pieces are ranked by remaining cards (the more the better).
We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier!
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or draws from the facedown stack, until each player has taken 3.
# One after another, each player must plan a travel route by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to increase the cost of travel by an addtional card.
# One after another, each player travels from town to town. The current position of a player is indicated by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes
To travel on a road, a river or a lake, the player needs to pay with the cards in hand the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (Note: the 'Magic Cloud' Transportation Counter cannot be placed in the desert, as it's too hot for a Cloud there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
c57cd8daa62a4072f5c756b58bbe2784d44635f7
927
926
2013-08-18T05:38:33Z
Chazm
3718
/* Variant */
wikitext
text/x-wiki
== Goal of the game ==
Visiting as many cities as possible in Elfenland over 4 rounds.
At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having an equal number of Town Pieces are ranked by remaining cards (the more the better).
We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier!
== Round overview ==
A round is split into phases:
# Each player fills his hand up to 8 cards and gets a secret Transportation Counter.
# One after another, each player chooses a Transportation Counter from the 5 visible or draws from the facedown stack, until each player has taken 3.
# One after another, each player must plan a travel route by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to increase the cost of travel by an addtional card.
# One after another, each player travels from town to town. The current position of a player is indicated by the Elf Boot of his color, initially set on the biggest town, Elvenhold.
At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter.
== Travel rules ==
Players can travel :
* on the roads on which a Transportation Counter has been set
* on the rivers
* on the lakes
To travel on a road, a river or a lake, the player needs to pay with the cards in hand the cost matching the terrain of the road and the means of transport used.
For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (Note: the 'Magic Cloud' Transportation Counter cannot be placed in the desert, as it's too hot for a Cloud there).
Also :
* To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows).
* To cross a lake, you need to pay two 'Raft' cards.
* If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type.
* If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road).
== Variant ==
In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round.
If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there.
This variant gives more tactical depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game.
'''Have a good game!'''
908794728060afee29a7eab7dd4e91cc500b128b
Reputation
0
17
904
165
2013-07-09T05:27:59Z
Jest phulin
3510
/* Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png */
wikitext
text/x-wiki
[[Category:Help]]
== What is reputation ? ==
On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance.
To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items:
* Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png)
* % of games you finished
* % of games you finished with no clock penalties
Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits.
== How to increase my reputation / what makes my reputation decrease ? ==
At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks.
* a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player.
* a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player.
You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change.
As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player.
By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information.
Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up.
== Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png ==
* Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game.
* When you need some time to think, click on "I would like to think a little" link.
* Always stay calm: it's a game.
* Don't press your opponent to play if he has some time left.
* If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does.
* Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!).
* Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation.
== What are the consequences of a bad reputation ? ==
A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you.
It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents.
67cf8fc8799861af33ddd3c786489e404d2ed3fb
Privacy
0
128
905
2013-07-09T06:22:06Z
Een
3
Created page with "To create an account, you need to provide an email, user name and password. You can also complete your player profile with some other data. We store this data. Yep. It would ..."
wikitext
text/x-wiki
To create an account, you need to provide an email, user name and password.
You can also complete your player profile with some other data.
We store this data. Yep. It would be pretty annoying for you to enter it each time you visit ;)
If you are 'internet paranoid' and you never provide any website with accurate personal information, congratulations! You can skip this section.
If you are not, congratulations! You can also skip this section which is intended only for 'internet paranoid' people anyway... It has been written for compliance with some social network authentication policy (take your bet, there is only two - oh, wait, if you are reading this you probably know). Well, to be fair, I could have left it empty too, the only check made by said social network being that the page exists. But, what would have been the fun in that?
If you are still interested to read on some stuff instead of going straight to playing:
* Your password is stored encrypted, but the usual precautionary measures apply. You should use a strong password and not use the same one that for sensitive websites. Some people would say never to use the same password, but this looks like excessive blunt force to the head, except for websites with very sensitive information. Shouldn't be the case on a gaming website, but hey, do as you please.
* We don't share your email with third parties without your consent. Your consent may be implicit in some obvious cases (such as if you take part in a contest with prizes from a publisher, as it will be needed for the publisher to contact you to redeem the prize).
* Your profile information is visible to other players, as well as your gaming history on the website. So, since anyone can create an account on the site, it should be considered public information. But if you use a pseudonym for your username, it shouldn't be easy to link it to your real identity (in case you would be worried about that).
Hope this all sounds reasonable to you, and that you can now enjoy Board Game Arena without second thoughts!
Cheers and doughnuts,
The admins.
936ac1f56e7544f713799cdf86cc4e3b858babbf
The Boss
0
46
906
423
2013-07-10T03:32:08Z
Stationary
3106
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
== Description ==
Each city, except '''Chicago''', has one hidden card underneath it.
The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city.
Each round, each player:
1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city.
2) Must play a card from your hand, revealing that information about the city.
When everybody has 2 cards in their hand, the police card is turned over.
If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished.
When everybody is out of cards, reveal the face down cards.
Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points.
If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn.
If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game.
'''Chicago'''
Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space right each round.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
31c2382f9f02f6aec6f8b1aa93cb206bb8f445ff
Gamehelpreversi
0
124
907
868
2013-07-15T21:15:37Z
Januszk0
3262
Opis
wikitext
text/x-wiki
Othello znane również pod nazwą Reversi to wciągająca gra logiczna, której korzenie sięgają XVIII wieku. W grę od XIX wieku gra niemal cała Europa. O jej wielkiej popularności zadecydowały proste reguły (prostsze niż warcabów) i bogactwo kombinacyjne dorównujące szachom. Od tych ostatnich gra jest jednak zdecydowanie bardziej dynamiczna.
== Zasady gry: ==
Rozgrywka toczy się na kwadratowej planszy podzielonej na 64 pola (8x8).
Każdy z graczy ma dostęp do wspólnego zestawu dwustronnych pionków (zwyczajowo, z jedną stroną białą, a drugą czarną). Gracze na zmianę wykonują ruchy dokładając na planszy pionki w swoim kolorze.
Pionki należy układać w taki sposób, aby pomiędzy pionkami gracza (poziomo, pionowo lub na skos) znalazła się jak największa ilość pionków przeciwnika. Po wykonaniu ruchu, wszystkie te pionki zostają przejęte i zmieniają kolor. Jeżeli gracz nie może wykonać dozwolonego przepisami posunięcia, musi pauzować (traci kolejkę).
Celem gry jest ułożenie na planszy jak największej ilości pionków, tak aby zamienić pionki przeciwnika na własne.
Wygrywa ten z graczy, którego większa liczba pionków znajduje się na planszy po zakończeniu gry.
W przypadku równej ilości pionków, gra kończy się remisem.
27f5626440fd71b896475a030a6b7ec0076ee359
908
907
2013-07-15T21:19:16Z
Januszk0
3262
Blanked the page
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
909
908
2013-07-15T21:20:35Z
Januszk0
3262
wikitext
text/x-wiki
[http://en.wikipedia.org/wiki/Reversi]
fe37062068d582dcb198fb6c0e2dff2371bc9a86
910
909
2013-07-15T21:25:51Z
Januszk0
3262
wikitext
text/x-wiki
[English Rules: Link][http://en.wikipedia.org/wiki/Reversi]
245acab3bf59561ee3167722bfe3b03c5fb3d769
Faq
0
3
911
659
2013-07-18T18:27:30Z
Guszty
3271
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
94dea1133bbc8858fde6d481215ca43bf31342b8
Gamehelpcantstop
0
35
912
757
2013-07-25T17:01:39Z
Chaotic iak
3338
wikitext
text/x-wiki
Can't Stop is a game involving rolling dice and knowing when to stop pushing one's luck.
==Rules==
Can't Stop is played with a board consisting of 11 columns, numbered from 2 to 12, four dice, and three temporary pieces.
===Splitting dice===
On a player's turn, they roll the four dice, split it to two groups however they like, then advance a step on each column whose sum is equal to some group of the dice.
Examples:
* Roll: 3,3,4,4. One can split it to 3,3 and 4,4, advancing a step on each of columns 6 and 8, or 3,4 and 3,4, advancing two steps on column 7.
* Roll: 2,3,4,5. One can split it in three ways: 2,3 and 4,5 (columns 5 and 9), 2,4 and 3,5 (columns 6 and 8), or 2,5 and 3,4 (columns 7 and 7).
* Roll: 4,4,4,6. There is only one way to split it, 4,4 and 4,6, which means columns 8 and 10.
* Roll: 1,1,1,1. There is only one way to split it, 1,1 and 1,1, which means columns 2 and 2.
===Temporary pieces===
In a turn, a player may only advance in three columns. The temporary pieces are to help the player in keeping track their progresses. However, one must make as many moves as possible.
Examples:
* One hasn't moved at all and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, advancing on columns 5 and 9. This is allowed; they advanced on columns 5,9. They may not choose to advance only on column 5 or only on column 9 because they must perform all moves possible.
* One has moved on columns 4 and 5 and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, advancing on columns 5 and 9. This is allowed; they advanced on columns 4,5,9.
* One has moved on columns 2 and 3 and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, and so should have advanced on columns 5 and 9. But this is not allowed; it makes them advance on four columns. They must pick either 5 or 9 to advance from.
* One has moved on columns 2, 3, and 12 and rolled 2,3,4,5. No matter how they split the dice, they cannot advance.
===Stopping one's turn===
A player keeps their turn until they state to stop or they cannot advance (like the last of the examples above). In the former case, the temporary pieces are made permanent; they will continue from the positions they have now. In the latter case, the temporary pieces are removed; their position is rolled back to before they have started their turn.
Examples:
* One decides to stop after advancing 3 steps on column 7, 2 steps on column 8, and 1 step on column 9, after previously have advanced 4 steps on column 6 and 3 steps on column 9. Now their position is 4 steps on column 6, 3 steps on column 7, 2 steps on column 8, and 4 steps on column 9.
* One advanced 3 steps on column 7, 2 steps on column 8, and 1 step on column 9, after previously have advanced 4 steps on column 6 and 3 steps on column 9, but then cannot advance. Their position is rolled back to only 4 steps on column 6 and 3 steps on column 9.
===Completing a column===
When one decides to stop and they have reached the end of some column, that column is scored for that player and no other player may advance in that column. For example, if column 5 has been scored and one splits a 2,3,4,5 to 2,3 and 4,5, they cannot advance on column 5 because it has been scored.
===Winning condition===
When one scores three columns, they win.
==Strategy==
The strategy of the game revolves on knowing when to stop. As one keeps playing, they still have the risk of losing all progress on the turn; stopping will save the progress but gives the other players a turn each. Knowing which is more beneficial helps.
Columns with more extreme numbers are less probable (a 2 is only scored by a 1,1 and a 12 is only scored by a 6,6, while a 7 is scored by six pairs of dice), so they have less steps to work on. One's strategy can also revolve on choosing whether to aim for middle columns or extreme columns.
b66171fad98a092b617274bc96550af3a344bd51
913
912
2013-08-03T21:30:44Z
Theotherk
3645
/* Splitting dice */
wikitext
text/x-wiki
Can't Stop is a game involving rolling dice and knowing when to stop pushing one's luck.
==Rules==
Can't Stop is played with a board consisting of 11 columns, numbered from 2 to 12, four dice, and three temporary pieces.
===Splitting dice===
On a player's turn, they roll the four dice, split the four dice to two groups of two dice however they like, then advance a step on each column whose sum is equal to some group of the dice.
Examples:
* Roll: 3,3,4,4. One can split it to 3,3 and 4,4, advancing a step on each of columns 6 and 8, or 3,4 and 3,4, advancing two steps on column 7.
* Roll: 2,3,4,5. One can split it in three ways: 2,3 and 4,5 (columns 5 and 9), 2,4 and 3,5 (columns 6 and 8), or 2,5 and 3,4 (columns 7 and 7).
* Roll: 4,4,4,6. There is only one way to split it, 4,4 and 4,6, which means columns 8 and 10.
* Roll: 1,1,1,1. There is only one way to split it, 1,1 and 1,1, which means columns 2 and 2.
===Temporary pieces===
In a turn, a player may only advance in three columns. The temporary pieces are to help the player in keeping track their progresses. However, one must make as many moves as possible.
Examples:
* One hasn't moved at all and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, advancing on columns 5 and 9. This is allowed; they advanced on columns 5,9. They may not choose to advance only on column 5 or only on column 9 because they must perform all moves possible.
* One has moved on columns 4 and 5 and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, advancing on columns 5 and 9. This is allowed; they advanced on columns 4,5,9.
* One has moved on columns 2 and 3 and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, and so should have advanced on columns 5 and 9. But this is not allowed; it makes them advance on four columns. They must pick either 5 or 9 to advance from.
* One has moved on columns 2, 3, and 12 and rolled 2,3,4,5. No matter how they split the dice, they cannot advance.
===Stopping one's turn===
A player keeps their turn until they state to stop or they cannot advance (like the last of the examples above). In the former case, the temporary pieces are made permanent; they will continue from the positions they have now. In the latter case, the temporary pieces are removed; their position is rolled back to before they have started their turn.
Examples:
* One decides to stop after advancing 3 steps on column 7, 2 steps on column 8, and 1 step on column 9, after previously have advanced 4 steps on column 6 and 3 steps on column 9. Now their position is 4 steps on column 6, 3 steps on column 7, 2 steps on column 8, and 4 steps on column 9.
* One advanced 3 steps on column 7, 2 steps on column 8, and 1 step on column 9, after previously have advanced 4 steps on column 6 and 3 steps on column 9, but then cannot advance. Their position is rolled back to only 4 steps on column 6 and 3 steps on column 9.
===Completing a column===
When one decides to stop and they have reached the end of some column, that column is scored for that player and no other player may advance in that column. For example, if column 5 has been scored and one splits a 2,3,4,5 to 2,3 and 4,5, they cannot advance on column 5 because it has been scored.
===Winning condition===
When one scores three columns, they win.
==Strategy==
The strategy of the game revolves on knowing when to stop. As one keeps playing, they still have the risk of losing all progress on the turn; stopping will save the progress but gives the other players a turn each. Knowing which is more beneficial helps.
Columns with more extreme numbers are less probable (a 2 is only scored by a 1,1 and a 12 is only scored by a 6,6, while a 7 is scored by six pairs of dice), so they have less steps to work on. One's strategy can also revolve on choosing whether to aim for middle columns or extreme columns.
6de82fa759a9e714493e081febed1557c7456e7f
Club Board Game Arena
0
8
914
876
2013-08-08T03:14:53Z
Earl of essence
3660
/* Why can't you just have a standard donation system where I can choose any money amount ? */
wikitext
text/x-wiki
==Why can't you just have a standard donation system where I can choose any money amount ?==
With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors.
==Is it mandatory to join the club ?==
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members.
==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif ==
When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif).
==What becomes of the money ?==
Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
325eb81bb9bae3c84de8268c42ea6b12de222a88
915
914
2013-08-08T03:16:02Z
Earl of essence
3660
/* Is it mandatory to join the club ? */
wikitext
text/x-wiki
==Why can't you just have a standard donation system where I can choose any money amount ?==
With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors.
==Is it mandatory to join the club ?==
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members.
==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif ==
When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif).
==What becomes of the money ?==
Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
a9b1fab3effc1c29a439f7e5b1b53f26a00cad37
916
915
2013-08-08T03:17:13Z
Earl of essence
3660
/* What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif */
wikitext
text/x-wiki
==Why can't you just have a standard donation system where I can choose any money amount ?==
With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors.
==Is it mandatory to join the club ?==
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members.
==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif ==
When you join Board Game Arena, you get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allows you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non-member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif).
==What becomes of the money ?==
Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
b5ffe68707f95aedf17704f721af0a8070495584
917
916
2013-08-08T03:18:25Z
Earl of essence
3660
/* What becomes of the money ? */
wikitext
text/x-wiki
==Why can't you just have a standard donation system where I can choose any money amount ?==
With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time.
Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors.
==Is it mandatory to join the club ?==
Of course not.
You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members.
==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif ==
When you join Board Game Arena, you get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allows you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non-member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif).
==What becomes of the money ?==
Board Game Arena's service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost).
Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)...
A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone !
57edae9e0c931f66c9fd4c5ab1c3ddd8b1f06828
Getting started
0
10
918
23
2013-08-08T03:23:22Z
Earl of essence
3660
wikitext
text/x-wiki
[[Category:Help]]
With '''Board Game Arena''' you can play within a few clicks.
By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables waiting for players.
You can join a game by clicking on "View table" then "Join game".
If you prefer, you can create a new game table: click on the "Launch table" button that corresponds to the game you want to play, and wait for your opponents.
Important to know before you start:
* It's much better to join a table already created than to create a new one.
* For most popular games you will find opponents at any time. For the others, try to connect around peak hour (around 22h CEST) to maximize your chances.
* When you start a game you can't leave the table until it ends. If you leave you will receive a penalty which will create difficulties finding opponents later.
a757320af56ced6014012dfea845fb0ec8c45592
Gamehelptzolkin
0
129
919
2013-08-09T14:34:28Z
Edgar
3667
Created page with " == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''P..."
wikitext
text/x-wiki
== '''For Each Round''' ==
- Each player takes their turn, going around the table
- On a food day, feed your workers and take your rewards
- Advance the Calendar
== '''Player turn''' ==
- '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple)
- '''Either place workers OR pick up workers'''
-- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers
-- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either
--- Use the action where your worker was standing
--- Use a lower action on the wheel from where your worker was standing(if not
standing on a free action space,pay 1 corn for each step back)
--- Do nothing.
== '''Food Day''' ==
-'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for.
-- For each worker not fed, you lose 3 points
-'''Take Rewards'''
--''Middle of Age (Brown days)''
--- Receive items shown on the left edge of themples from step you are on and all steps below
-- ''End of Age(Teal Days)''
--- Remove all Age 1 buildings and fill spaces with Age 2 buildings/
--- Receive points shown on the right edge of temples for the step you are on.
--- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus.
== '''Advance the Calendar''' ==
If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day.
Otherwise:
- The worker on the Starting Player space returns to the player
-- If this person was not the starting player, they take the starting player marker.
-- If they were the starting player, the starting player marker is moved to the player on his left
- Advance the Tzolk'in Gear one day.
- The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears.
-- If you use this option. Flip your board to dark side up.
-- This does not avoid food days.
4bfacd574a92eebe81d97b17b85b3702ebb652cc
920
919
2013-08-10T02:18:35Z
Joseppr
1780
/* Advance the Calendar */
wikitext
text/x-wiki
== '''For Each Round''' ==
- Each player takes their turn, going around the table
- On a food day, feed your workers and take your rewards
- Advance the Calendar
== '''Player turn''' ==
- '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple)
- '''Either place workers OR pick up workers'''
-- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers
-- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either
--- Use the action where your worker was standing
--- Use a lower action on the wheel from where your worker was standing(if not
standing on a free action space,pay 1 corn for each step back)
--- Do nothing.
== '''Food Day''' ==
-'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for.
-- For each worker not fed, you lose 3 points
-'''Take Rewards'''
--''Middle of Age (Brown days)''
--- Receive items shown on the left edge of themples from step you are on and all steps below
-- ''End of Age(Teal Days)''
--- Remove all Age 1 buildings and fill spaces with Age 2 buildings/
--- Receive points shown on the right edge of temples for the step you are on.
--- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus.
== '''Advance the Calendar''' ==
If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day.
Otherwise:
- The worker on the Starting Player space returns to the player
-- If this person was not the starting player, they take the starting player marker.
-- If they were the starting player, the starting player marker is moved to the player on his left
- Advance the Tzolk'in Gear one day.
- The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears.
-- If you use this option, flip your board to dark side up.
-- This does not avoid food days.
a93481001a7c82b23c85cda088a16424ec014722
921
920
2013-08-10T02:19:54Z
Joseppr
1780
/* Food Day */
wikitext
text/x-wiki
== '''For Each Round''' ==
- Each player takes their turn, going around the table
- On a food day, feed your workers and take your rewards
- Advance the Calendar
== '''Player turn''' ==
- '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple)
- '''Either place workers OR pick up workers'''
-- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers
-- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either
--- Use the action where your worker was standing
--- Use a lower action on the wheel from where your worker was standing(if not
standing on a free action space,pay 1 corn for each step back)
--- Do nothing.
== '''Food Day''' ==
-'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for.
-- For each worker not fed, you lose 3 points
-'''Take Rewards'''
--''Middle of Age (Brown days)''
--- Receive items shown on the left edge of themples from step you are on and all steps below
-- ''End of Age (Teal Days)''
--- Remove all Age 1 buildings and fill spaces with Age 2 buildings/
--- Receive points shown on the right edge of temples for the step you are on.
--- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus.
== '''Advance the Calendar''' ==
If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day.
Otherwise:
- The worker on the Starting Player space returns to the player
-- If this person was not the starting player, they take the starting player marker.
-- If they were the starting player, the starting player marker is moved to the player on his left
- Advance the Tzolk'in Gear one day.
- The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears.
-- If you use this option, flip your board to dark side up.
-- This does not avoid food days.
492a51ebdd36dc9ecb3fa747a046c5a54b18ca80
922
921
2013-08-10T18:26:35Z
Januszk0
3262
wikitext
text/x-wiki
== '''W każdej rundzie''' ==
- Gracze rozgrywają swoje tury zgodnie z ruchem wskazówek zegara
- W Dniu Żywienia, gracze żywią robotników i otrzymują nagrody
- Przestawiają kalendarz
== '''Tury graczy''' ==
- '''Prośba o kukurydzę:''' Jeśli masz 2 lub mniej koszy kukurydzy, można poprosić o kukurydzę, chyba że jesteś na dole wszystkich trzech świątyń. (Odrzuć całą kukurydzę i weź 3 kosze kukurydzy i przejdź o jeden stopień w dół jednej ze świątyń)
- '''Wyślij do pracy na kołach dowolną liczbę robotników lub zdejmij dowolną liczbę robotników z kół'''
-- ''Wysyłanie robotników do pracy'': Gracz płaci tyle koszów kukurydzy, ile wynosi numer pola akcji na które wysłał robotnika. Płaci się również dodatkowe kosze kukurydzy za każdego dodatkowego robotnika wysłanego w danej turze
-- ''Powrót robotników do wioski'': Można wybrać jednego lub więcej z twoich umieszczonych robotników. Dzięki każdemu powracającemu robotnikowi gracz może:
--- Wykonać akcję przy której stał robotnik w momencie zdjęcia,
--- Wykonać akcję z jednego z pól o niższym numerze na tym samym kole. Za każdy numer różnicy, gracz musi zapłacić 1 kosz kukurydzy,
--- Nie robić nic. Gracz zdejmuje tylko robotnika z koła.
== '''Dzień Żywienia''' ==
-'''Żywienie Robotników''' Każdy gracz musi zapłacić 2 kosze kukurydzy za każdego robotnika, którego ma w grze (na kole lub przed sobą. Gracz musi nakarmić, tylu robotników ile jest w stanie. - Za każdego nienakarmionego robotnika, traci 3 punkty zwycięstwa
-'''Weź nagrody'''
--''W środku epoki (Brązowo-pomarańczowe Dni Żywienia)''
--- Gracze otrzymują nagrody w postaci surowców i kryształowych czaszek,
-- ''Koniec epoki (Niebiesko-zielone Dni Żywienia)''
--- Usuń wszystkie budynki epoki 1 i wyłóżcie budynki epoki 2.
--- Gracz otrzymuje punkty zwycięstwa wskazane przez aktualnie zajmowany stopień w świątyni.
--- Gracz znajdujący się w danej świątyni na najwyższym stopniu spośród wszystkich graczy otrzymuje punkty bonusowe. Określają go liczby widniejące nad każdą świątynią. W przypadku remisu, wszyscy remisujący gracze otrzymują połowę premii.
== '''Przestawianie kalendarza''' ==
Jeśli nie ma robotnika na polu Pierwszeństwa żadnego gracza, należy umieścić 1 kosz kukurydzy na aktualnym zębie kalendarza Tzolk'in i przesunąć go o 1 dzień.
W przeciwnym razie:
- Robotnik znajdujący się na najwyżej numerowanym polu wraca do gracza
-- Jeśli tą osobą nie był Pierwszy Gracz, bierze znacznik Pierwszego Gracza.
-- Jeśli gracz zajmujący pole Pierwszeństwa posiada aktualnie znacznik Pierwszego Gracza, przekazuje go graczowi po swojej lewej stronie.
- Przestawić kalendarz Tzolk'in o jeden dzień.
- Gracz, który umieścił swojego robotnika na polu Pierwszeństwa może zdecydować, aby przesunąć kalendarz o jeden dodatkowy dzień, jeśli jego plansza nie jest obrócona ciemną stroną ku górze i w rezultacie jakiś robotnik nie zostałby zepchnięty z koła (a nie byłby zepchnięty przy obrocie kalendarza o 1 dzień).
-- W przypadku skorzystania z tej opcji, należy obrócić swoją planszę ciemną stroną w górę.
-- Przesunięcie kalendarza o 2 dni nie powoduje ominięcia Dnia Żywienia.
8021b92dcc87698161db6689bd4b6f24d3444c02
923
922
2013-08-10T18:31:57Z
Januszk0
3262
Undo revision 922 by [[Special:Contributions/Januszk0|Januszk0]] ([[User talk:Januszk0|talk]])
wikitext
text/x-wiki
== '''For Each Round''' ==
- Each player takes their turn, going around the table
- On a food day, feed your workers and take your rewards
- Advance the Calendar
== '''Player turn''' ==
- '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple)
- '''Either place workers OR pick up workers'''
-- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers
-- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either
--- Use the action where your worker was standing
--- Use a lower action on the wheel from where your worker was standing(if not
standing on a free action space,pay 1 corn for each step back)
--- Do nothing.
== '''Food Day''' ==
-'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for.
-- For each worker not fed, you lose 3 points
-'''Take Rewards'''
--''Middle of Age (Brown days)''
--- Receive items shown on the left edge of themples from step you are on and all steps below
-- ''End of Age (Teal Days)''
--- Remove all Age 1 buildings and fill spaces with Age 2 buildings/
--- Receive points shown on the right edge of temples for the step you are on.
--- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus.
== '''Advance the Calendar''' ==
If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day.
Otherwise:
- The worker on the Starting Player space returns to the player
-- If this person was not the starting player, they take the starting player marker.
-- If they were the starting player, the starting player marker is moved to the player on his left
- Advance the Tzolk'in Gear one day.
- The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears.
-- If you use this option, flip your board to dark side up.
-- This does not avoid food days.
492a51ebdd36dc9ecb3fa747a046c5a54b18ca80
Gamehelpjaipur
0
115
928
792
2013-09-03T06:18:06Z
Hofty
3828
wikitext
text/x-wiki
In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take.
On your turn, you take one of three actions:
# '''Take''' a single card or all the camels in the face up row.
#: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd.
#: You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.)
#: The card row is then replenished from the deck so it always has 5 cards at the start of a turn.
# '''Trade''' for 2 or more goods cards from the row.
#: You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand.
#: The cards your traded are added to the card row, so it will still have 5 cards.
# '''Sell''' cards to earn points.
#: You may sell one or more cards to earn points, but all the cards you sell must be the same color.
#: If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards.
#: Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token.
#: If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods).
#: The sold goods cards are discarded.
The game continues until either:
* Three piles of goods tokens are depleted; OR
* The card row cannot be replenished.
: At that point, players total the points they have on their earned goods tokens and bonus tokens.
: In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points.
: Whichever player earns more points total wins the round.
: Tie-breaker, in order:
:* Player with more bonus tokens wins the round;
:* Player with more goods tokens wins the round;
After the round, the game resets and new hands are dealt.
The first player to win two rounds wins the game.
e52209133c4cf5f83fe7b582a15608cf0196cdbe
How to join BGA developer team?
0
83
929
777
2013-09-30T15:58:44Z
Sourisdudesert
1
wikitext
text/x-wiki
Registering on BGA Studio is simple and automatic from:
http://en.studio.boardgamearena.com
To register, you must agree with [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf ''''terms & conditions' document''']. It's very light, so as to get to the fun part faster.
Once registered, you will get by email
* one login / password to access files through SFTP
* one login / password to access the database (for your games in progress)
* ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing.
== Ok, I registered, how to start? ==
Then... well that's all, you can start!
See [[Studio#Great.2C_I.27m_in.21_..._How_should_I_start.3F|Great, I'm in! ... How should I start?]]
fb343543e19b566d00dc6f09ee976e3b6833157c
Studio
0
49
930
892
2013-09-30T16:00:09Z
Sourisdudesert
1
/* What is Board Game Arena Studio? */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
BGA Studio website:
http://en.studio.boardgamearena.com
(original announcement on BGA forum: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973)
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio logs]]
* [[Studio back-office]]
* [[Studio FAQ]]
== BGA Developer team organization ==
* [[Steps to create a BGA game]]
* [[Post-release phase]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
c35e1c0c136bab1179c58e3975449dc99f1e54fe
951
930
2013-09-30T16:39:22Z
Sourisdudesert
1
/* Other components */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
BGA Studio website:
http://en.studio.boardgamearena.com
(original announcement on BGA forum: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973)
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game meta-information: gameinfos.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio logs]]
* [[Studio back-office]]
* [[Studio FAQ]]
== BGA Developer team organization ==
* [[Steps to create a BGA game]]
* [[Post-release phase]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
b535d7773a8c8fd1bca0347173a6b7d9be556f76
First steps with BGA Studio
0
111
931
775
2013-09-30T16:01:31Z
Sourisdudesert
1
/* Connect to your SFTP folder and to the BGA Studio website */
wikitext
text/x-wiki
== Connect to your SFTP folder and to the BGA Studio website ==
After your account has been created, you will get by email:
* the name of the SFTP server to connect to
* your SFTP login and password
* ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them.
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example)
# Check that your home folder contains :
#* One folder for each of the three example games (reversi, hearts, gomoku)
#* One folder matching the game you will be developing
#* One 'resources.html' file
# Open the resources.html file, it contains :
#* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file
#* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two)
#* The URL pointing to the web administration tool for the BGA Studio database.
# Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user.
== Launch your game and check how to update it ==
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
== Commit your changes ==
Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development.
Here is how to go through your first commit:
# Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared);
# Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button;
# Check the log for errors, it should end with the following lines:
Transmitting file data .
Committed revision #revision number#.
HAL says: done.
NB: you should also commit each time you make a change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do so.
== That's all! ==
Now you know about the basics of updating your game on BGA Studio and testing your changes.
For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]].
586dd4594ea28af9e205f5669a05e5e8aed64c46
932
931
2013-09-30T16:04:24Z
Sourisdudesert
1
/* Connect to your SFTP folder and to the BGA Studio website */
wikitext
text/x-wiki
== Connect to your SFTP folder and to the BGA Studio website ==
After your account has been created, you will get by email:
* the name of the SFTP server to connect to
* your SFTP login and password
* ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them.
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example)
# Check that your home folder contains one folder for each of the three example games (reversi, hearts, gomoku). Each time you create a new game project, one additional folder is added to your "home" folder.
# Open the resources.html file, it contains :
#* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file
#* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two)
#* The URL pointing to the web administration tool for the BGA Studio database.
# Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user.
== Launch your game and check how to update it ==
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
== Commit your changes ==
Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development.
Here is how to go through your first commit:
# Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared);
# Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button;
# Check the log for errors, it should end with the following lines:
Transmitting file data .
Committed revision #revision number#.
HAL says: done.
NB: you should also commit each time you make a change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do so.
== That's all! ==
Now you know about the basics of updating your game on BGA Studio and testing your changes.
For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]].
af565310fc4858efe51b38ad1c807020ce5aae1a
933
932
2013-09-30T16:08:02Z
Sourisdudesert
1
wikitext
text/x-wiki
== Connect to the BGA Studio website ==
Go to BGA Studio website:
http://en.studio.boardgamearena.com
Choose one of your 10 accounts (ex: myusername0), and login into the website - as you would do for Board Game Arena.
== Check projects in progress and available game licences ==
On the left menu, you can check game projects under development and available game licences. From this point, you can choose what you want to do:
* Join an existing project.
* Create a new project.
* Try to get a licence for a game you don't see in the "available game licences" page (see how-to on "available licences" page).
== Connect to your SFTP folder and to the BGA Studio website ==
After your account has been created, you will get by email:
* the name of the SFTP server to connect to
* your SFTP login and password
* ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them.
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example)
# Check that your home folder contains one folder for each of the three example games (reversi, hearts, gomoku). Each time you create a new game project, one additional folder is added to your "home" folder.
# Open the resources.html file, it contains :
#* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file
#* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two)
#* The URL pointing to the web administration tool for the BGA Studio database.
# Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user.
== Launch your game and check how to update it ==
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
== Commit your changes ==
Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development.
Here is how to go through your first commit:
# Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared);
# Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button;
# Check the log for errors, it should end with the following lines:
Transmitting file data .
Committed revision #revision number#.
HAL says: done.
NB: you should also commit each time you make a change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do so.
== That's all! ==
Now you know about the basics of updating your game on BGA Studio and testing your changes.
For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]].
4db9f5edfea9064f7f121c960821ffa45437f95e
934
933
2013-09-30T16:15:35Z
Sourisdudesert
1
wikitext
text/x-wiki
== Connect to the BGA Studio website ==
Go to BGA Studio website:
http://en.studio.boardgamearena.com
Choose one of your 10 accounts (ex: myusername0), and login into the website - as you would do for Board Game Arena.
== Check projects in progress and available game licences ==
On the left menu, you can check game projects under development and available game licences. From this point, you can choose what you want to do:
* Join an existing project.
* Create a new project.
* Try to get a licence for a game you don't see in the "available game licences" page (see how-to on "available licences" page).
== Create a new game project ==
You can do most of projects-related operation from "Control Panel / Manage games". In particular, you can create a new project automatically from there.
== Connect to your SFTP folder ==
From the initial email from the Studion you get:
* the name of the SFTP server to connect to
* your SFTP login and password
Using this information:
# Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example)
# Check that your home folder contains one folder for each of the three example games (reversi, hearts, gomoku). If you have already created a new game project, one additional folder should be in your "home" folder.
== Let's code! ==
Now, you can try to launch a new game on BGA Studio from the "Play now" menu entry, as you would do on Board Game Arena website.
# Find your game in the 'Play now' section and launch a table
# Use the 'I want between X and X' players to tick down the maximum players number to the minimum
# Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'.
# Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save.
# Go back to your browser and refresh, check that the game zone has updated.
# Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game.
# Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image.
# Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated.
Then you can modify the provided skeleton and begin to develop your game :)
== Commit your changes ==
Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development.
You can automatically commit your sources in the repository from "Control Panel / Manage Games / Your games / Commit my modifications". Then:
# Enter your commit comment (such as 'My first commit') then hit the 'Submit' button;
# Check the log for errors, it should end with the following lines:
Transmitting file data .
Committed revision #revision number#.
HAL says: done.
== That's all! ==
Now you know about the basics of updating your game on BGA Studio and testing your changes.
For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]].
84374110062c7881c18ce66a4fc7739285e46ba1
Tutorial reversi
0
57
935
759
2013-09-30T16:16:56Z
Sourisdudesert
1
/* Let it look like Reversi */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('img/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('../../img/reversi/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "states.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* Server side, check the move is correct, apply Reversi rules and jump to next player.
* Client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$player_id = self::getActivePlayerId();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
To make the statistics work, we have to initialize them in state.inc.php:
<pre>
// Statistics existing for each player
"player" => array(
"discPlayedOnCorner" => array( "id"=> 10,
"name" => totranslate("Discs played on a corner"),
"type" => "int" ),
"discPlayedOnBorder" => array( "id"=> 11,
"name" => totranslate("Discs played on a border"),
"type" => "int" ),
"discPlayedOnCenter" => array( "id"=> 12,
"name" => totranslate("Discs played on board center part"),
"type" => "int" ),
"turnedOver" => array( "id"=> 13,
"name" => totranslate("Number of discs turned over"),
"type" => "int" )
)
</pre>
A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Activate next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appear automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handles the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Make these discs blink and set them to the specified color
for( var i in notif.args.turnedOver )
{
var token = notif.args.turnedOver[ i ];
// Make the token blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeOut( {
node: 'token_'+token.x+'_'+token.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'tokencolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
5bf435974f89c8abeb2713fa66580b3e0b38160f
936
935
2013-09-30T16:17:31Z
Sourisdudesert
1
/* Make the squares appears */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('img/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('img/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('../../img/reversi/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "states.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* Server side, check the move is correct, apply Reversi rules and jump to next player.
* Client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$player_id = self::getActivePlayerId();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
To make the statistics work, we have to initialize them in state.inc.php:
<pre>
// Statistics existing for each player
"player" => array(
"discPlayedOnCorner" => array( "id"=> 10,
"name" => totranslate("Discs played on a corner"),
"type" => "int" ),
"discPlayedOnBorder" => array( "id"=> 11,
"name" => totranslate("Discs played on a border"),
"type" => "int" ),
"discPlayedOnCenter" => array( "id"=> 12,
"name" => totranslate("Discs played on board center part"),
"type" => "int" ),
"turnedOver" => array( "id"=> 13,
"name" => totranslate("Number of discs turned over"),
"type" => "int" )
)
</pre>
A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Activate next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appear automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handles the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Make these discs blink and set them to the specified color
for( var i in notif.args.turnedOver )
{
var token = notif.args.turnedOver[ i ];
// Make the token blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeOut( {
node: 'token_'+token.x+'_'+token.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'tokencolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
282982cfad91e05e90904077f85b206b8d802497
937
936
2013-09-30T16:17:49Z
Sourisdudesert
1
/* The discs */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('img/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('img/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('img/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "states.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* Server side, check the move is correct, apply Reversi rules and jump to next player.
* Client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$player_id = self::getActivePlayerId();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
To make the statistics work, we have to initialize them in state.inc.php:
<pre>
// Statistics existing for each player
"player" => array(
"discPlayedOnCorner" => array( "id"=> 10,
"name" => totranslate("Discs played on a corner"),
"type" => "int" ),
"discPlayedOnBorder" => array( "id"=> 11,
"name" => totranslate("Discs played on a border"),
"type" => "int" ),
"discPlayedOnCenter" => array( "id"=> 12,
"name" => totranslate("Discs played on board center part"),
"type" => "int" ),
"turnedOver" => array( "id"=> 13,
"name" => totranslate("Number of discs turned over"),
"type" => "int" )
)
</pre>
A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Activate next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appear automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handles the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Make these discs blink and set them to the specified color
for( var i in notif.args.turnedOver )
{
var token = notif.args.turnedOver[ i ];
// Make the token blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeOut( {
node: 'token_'+token.x+'_'+token.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'tokencolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
aa698a8b78cfb8f1505e1f220027722caa717164
Tutorial gomoku
0
73
938
709
2013-09-30T16:19:55Z
Sourisdudesert
1
/* Setup the board */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( 'img/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
// At the end of the slide, update the intersection
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' );
dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color );
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
// We can now destroy the stone since it is now visible through the change in style of the intersection
dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y );
}));
slide.play();
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( '../../img/gomoku/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
e99b68b52465537142e09fa28207afcf7ee2c1fb
939
938
2013-09-30T16:21:42Z
Sourisdudesert
1
/* Manage states and events */
wikitext
text/x-wiki
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row).
== You will start from our 'emtpy game' template ==
Here is how your games looks by default when it has just been created:
[[File:Gomoku tuto1.png]]
== Setup the board ==
Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access.
Edit .tpl to add some divs for the board in the HTML. For example:
<pre>
<div id="gmk_game_area">
<div id="gmk_background">
<div id="gmk_goban">
</div>
</div>
</div>
</pre>
Edit .css to set the div sizes and positions and show the image of the board as background.
<pre>
#gmk_game_area {
text-align: center;
position: relative;
}
#gmk_background {
width: 620px;
height: 620px;
position: relative;
display: inline-block;
}
#gmk_goban {
background-image: url( 'img/goban.jpg');
width: 620px;
height: 620px;
position: absolute;
}
</pre>
[[File:Gomoku tuto2.png]]
== Setup the backbone of your game ==
Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any).
<pre>
CREATE TABLE IF NOT EXISTS `intersection` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`coord_x` tinyint(2) unsigned NOT NULL,
`coord_y` tinyint(2) unsigned NOT NULL,
`stone_color` varchar(8) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
</pre>
Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database.
<pre>
// Insert (empty) intersections into database
$sql = "INSERT INTO intersection (coord_x, coord_y) VALUES ";
$values = array();
for ($x = 0; $x < 19; $x++) {
for ($y = 0; $y < 19; $y++) {
$values[] = "($x, $y)";
}
}
$sql .= implode( $values, ',' );
self::DbQuery( $sql );
</pre>
Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database.
<pre>
// Intersections
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection ";
$result['intersections'] = self::getCollectionFromDb( $sql );
</pre>
Edit .tpl to create a template for intersections.
<pre>
var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>';
</pre>
Define the styles for the intersection divs.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
}
</pre>
Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections.
<pre>
// Setup intersections
for( var id in gamedatas.intersections )
{
var intersection = gamedatas.intersections[id];
dojo.place( this.format_block('jstpl_intersection', {
x:intersection.coord_x,
y:intersection.coord_y,
stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color)
} ), $ ( 'gmk_background' ) );
var x_pix = this.getXPixelCoordinates(intersection.coord_x);
var y_pix = this.getYPixelCoordinates(intersection.coord_y);
this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play();
if (intersection.stone_color != null) {
// This intersection is taken, it shouldn't appear as clickable anymore
dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' );
}
}
</pre>
Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right.
<pre>
.gmk_intersection {
width: 30px;
height: 30px;
position: relative;
background-color: blue;
opacity: 0.3;
}
</pre>
You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client.
* Declare your constants in material.inc.php (this will be automatically included in your .game.php)
<pre>
$this->gameConstants = array(
"INTERSECTION_WIDTH" => 30,
"INTERSECTION_HEIGHT" => 30,
"INTERSECTION_X_SPACER" => 2.8, // Float
"INTERSECTION_Y_SPACER" => 2.8, // Float
"X_ORIGIN" => 0,
"Y_ORIGIN" => 0,
);
</pre>
* In .game.php->getAllDatas(), add the constants to the result array
// Constants
$result['constants'] = $this->gameConstants;
* In .js constructor, define a class variable for constants
// Game constants
this.gameConstants = null;
* In .js->setup() assign the constants to this variable
this.gameConstants = gamedatas.constants;
* Then use it in your getXPixelCoordinates and getYPixelCoordinates functions
getXPixelCoordinates: function( intersection_x )
{
return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']);
},
getYPixelCoordinates: function( intersection_y )
{
return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']);
},
Here is what you should get:
[[File:Gomoku tuto3.png]]
== Manage states and events ==
Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over.
The first state requires an action from the player, so its type is 'activeplayer'.
The two others are automatic actions for the game, so their type is 'game'.
We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true.
<pre>
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a stone'),
"descriptionmyturn" => clienttranslate('${you} must play a stone'),
"type" => "activeplayer",
"possibleactions" => array( "playStone" ),
"transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 )
),
3 => array(
"name" => "checkEndOfGame",
"description" => '',
"type" => "game",
"action" => "stCheckEndOfGame",
"updateGameProgression" => true,
"transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 )
),
4 => array(
"name" => "nextPlayer",
"description" => '',
"type" => "game",
"action" => "stNextPlayer",
"transitions" => array( "" => 2 )
),
</pre>
Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy:
<pre>
function stNextPlayer()
{
self::trace( "stNextPlayer" );
// Go to next player
$active_player = self::activeNextPlayer();
self::giveExtraTime( $active_player );
$this->gamestate->nextState();
}
</pre>
Add onclick events on intersections in .js->setup()
// Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand)
this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection");
Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters
<pre>
onClickIntersection: function( evt )
{
console.log( '$$$$ Event : onClickIntersection' );
dojo.stopEvent( evt );
if( ! this.checkAction( 'playStone' ) )
{ return; }
var node = evt.currentTarget.id;
var coord_x = node.split('_')[1];
var coord_y = node.split('_')[2];
console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' );
if ( this.isCurrentPlayerActive() ) {
this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} );
}
},
</pre>
Add this action function in .action.php, retrieving parameters and calling the appropriate game action
<pre>
public function playStone()
{
self::setAjaxMode();
// Retrieve arguments
// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method
$coord_x = self::getArg( "coord_x", AT_posint, true );
$coord_y = self::getArg( "coord_y", AT_posint, true );
// Then, call the appropriate method in your game logic, like "playCard" or "myAction"
$this->game->playStone( $coord_x, $coord_y );
self::ajaxResponse( );
}
</pre>
Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state.
<pre>
function playStone( $coord_x, $coord_y )
{
// Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php)
self::checkAction( 'playStone' );
$player_id = self::getActivePlayerId();
// Check that this intersection is free
$sql = "SELECT
id, coord_x, coord_y, stone_color
FROM
intersection
WHERE
coord_x = $coord_x
AND coord_y = $coord_y
AND stone_color is null
";
$intersection = self::getObjectFromDb( $sql );
if ($intersection == null) {
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
}
// Get player color
$sql = "SELECT
player_id, player_color
FROM
player
WHERE
player_id = $player_id
";
$player = self::getNonEmptyObjectFromDb( $sql );
$color = ($player['player_color'] == 'ffffff' ? 'white' : 'black');
// Update the intersection with a stone of the appropriate color
$intersection_id = $intersection['id'];
$sql = "UPDATE
intersection
SET
stone_color = '$color'
WHERE
id = $intersection_id
";
self::DbQuery($sql);
// Notify all players
self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y),
'coord_x' => $coord_x,
'coord_y' => $coord_y,
'color' => $color
) );
// Go to next game state
$this->gamestate->nextState( "stonePlayed" );
}
</pre>
Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received.
<pre>
setupNotifications: function()
{
console.log( 'notifications subscriptions setup' );
dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" );
}
</pre>
Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function.
<pre>
notif_stonePlayed: function( notif )
{
console.log( '**** Notification : stonePlayed' );
console.log( notif );
// Create a stone
dojo.place( this.format_block('jstpl_stone', {
stone_type:'stone_' + notif.args.color,
x:notif.args.coord_x,
y:notif.args.coord_y
} ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) );
// Place it on the player panel
this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) );
// Animate a slide from the player panel to the intersection
dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 );
var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 );
dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() {
// At the end of the slide, update the intersection
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' );
dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color );
dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' );
// We can now destroy the stone since it is now visible through the change in style of the intersection
dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y );
}));
slide.play();
},
</pre>
For this function to work properly, you also need:
* to declare a stone javascript template in your .tpl file.
<pre>
var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>';
</pre>
* to define the css styles for the stones
<pre>
.gmk_stone {
width: 30px;
height: 30px;
position: absolute;
background-image: url( 'img/stones.png');
}
.no_stone { background-position: -60px 0px; }
.stone_black { background-position: 0px 0px; }
.stone_white { background-position: -30px 0px; }
</pre>
These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like:
[[File:Gomoku stones.png]]
The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this:
* we define in the css file the 'clickable' css class
<pre>
.clickable {
cursor: pointer;
}
.clickable:hover { background-position: -90px 0px; }
</pre>
* in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
if( this.isCurrentPlayerActive() )
{
var queueEntries = dojo.query( '.no_stone' );
for(var i=0; i<queueEntries.length; i++) {
dojo.addClass( queueEntries[i], 'clickable' );
}
}
}
},
</pre>
The basic game turn is implemented: you can now drop some stones!
[[File:Gomoku tuto4.png]]
== Cleanup your styles ==
Remove temporary css visualisation helpers : looks good!
[[File:Gomoku tuto5.png]]
== Implement rules and end of game conditions ==
Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame():
* modify the default colors for players to white and black
$default_colors = array( "000000", "ffffff", );
* and at the end of the setup make the black player active
<pre>
// Black plays first
$sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' ";
$black_player = self::getNonEmptyObjectFromDb( $sql );
$this->gamestate->changeActivePlayer( $black_player['player_id'] );
</pre>
Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner).
<pre>
function getGameProgression()
{
// Compute and return the game progression
// Number of stones laid down on the goban over the total number of intersections * 100
$sql = "
SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null
";
$counter = self::getNonEmptyObjectFromDB( $sql );
return $counter['value'];
}
</pre>
Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so:
* declare a global 'end_of_game' variable in .game.php->Gomoku()
self::initGameStateLabels( array(
"end_of_game" => 10,
) );
* init that global variable to 0 in .game.php->setupNewGame()
self::setGameStateInitialValue( 'end_of_game', 0 );
* add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended.
<pre>
// Check if end of game has been met
if ($this->checkForWin( $coord_x, $coord_y, $color )) {
// Set active player score to 1 (he is the winner)
$sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id";
self::DbQuery($sql);
// Notify final score
$this->notifyAllPlayers( "finalScore",
clienttranslate( '${player_name} wins the game!' ),
array(
"player_name" => self::getActivePlayerName(),
"player_id" => $player_id,
"score_delta" => 1,
)
);
// Set global variable flag to pass on the information that the game has ended
self::setGameStateValue('end_of_game', 1);
// End of game message
$this->notifyAllPlayers( "message",
clienttranslate('Thanks for playing!'),
array(
)
);
}
</pre>
* Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw).
<pre>
function stCheckEndOfGame()
{
self::trace( "stCheckEndOfGame" );
$transition = "notEndedYet";
// If there is no more free intersections, the game ends
$sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null";
$free = self::getCollectionFromDb( $sql );
if (count($free) == 0) {
$transition = "gameEnded";
}
// If the 'end of game' flag has been set, end the game
if (self::getGameStateValue('end_of_game') == 1) {
$transition = "gameEnded";
}
$this->gamestate->nextState( $transition );
}
</pre>
* Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly.
<pre>
dojo.subscribe( 'finalScore', this, "notif_finalScore" );
this.notifqueue.setSynchronous( 'finalScore', 1500 );
</pre>
* Implement the function declared to handle the notification.
<pre>
notif_finalScore: function( notif )
{
console.log( '**** Notification : finalScore' );
console.log( notif );
// Update score
this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta );
},
</pre>
'''Test everything thoroughly... you are done!'''
[[File:Gomoku tuto6.png]]
5b632d978467043e546b8e53050a67a7c86201ad
Studio FAQ
0
53
940
831
2013-09-30T16:22:43Z
Sourisdudesert
1
/* I can't access the Studio back-office, I get a 'Not authorized' error message? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== I don't know the name to use to commit my game, what name should I use? ==
The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico).
It is the same name as the name used for the game folder in your SFTP access.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
When you modify these 2 files, you need to deploy the update from your BGA backoffice page.
== Should I use images free from copyright? ==
If you are developing a game in the public domain, yes (or you can make your own if you feel it's better).
If you are developing a game for which we have a licence, we will usually provide art files from the publisher.
4f4bdecc8aefcd03cb2a55b3275da02813136c01
941
940
2013-09-30T16:22:51Z
Sourisdudesert
1
/* I don't know the name to use to commit my game, what name should I use? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
BGA administrators will translate the game in French before the game release.
After the game release, the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
When you modify these 2 files, you need to deploy the update from your BGA backoffice page.
== Should I use images free from copyright? ==
If you are developing a game in the public domain, yes (or you can make your own if you feel it's better).
If you are developing a game for which we have a licence, we will usually provide art files from the publisher.
9702d3fd8ae2fc57912a7b38c8fb3fb1f582d33d
942
941
2013-09-30T16:23:26Z
Sourisdudesert
1
/* How can I provide translation in my language? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
The community will translate the game in all language after the game release with the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
When you modify these 2 files, you need to deploy the update from your BGA backoffice page.
== Should I use images free from copyright? ==
If you are developing a game in the public domain, yes (or you can make your own if you feel it's better).
If you are developing a game for which we have a licence, we will usually provide art files from the publisher.
8ebb6ee7fdf24f8caa59262dab1786dcc53fcf91
943
942
2013-09-30T16:25:25Z
Sourisdudesert
1
/* I updated the images in the 'img' folder of my game, but they don't show? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
The community will translate the game in all language after the game release with the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
'''Concerning game_box.png, game_icon.png and publisher.png''':
You must use "Reload game box image" function from "Control Panel / Manage Games / Your game" to make your change visible.
'''Concerning other images''':
Other images used during the game are immediately available without any action.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics, but they don't show? ==
When you modify these 2 files, you need to deploy the update from your BGA backoffice page.
== Should I use images free from copyright? ==
If you are developing a game in the public domain, yes (or you can make your own if you feel it's better).
If you are developing a game for which we have a licence, we will usually provide art files from the publisher.
0866a26dcc172d82d512489bf6e1883e7573515e
944
943
2013-09-30T16:26:51Z
Sourisdudesert
1
/* I added some game options / some game statistics, but they don't show? */
wikitext
text/x-wiki
This is a place where we will collect and answer frequently asked questions.
== What should I use to access the files through SFTP? ==
There is a lot of tools to do that. Use the one you are the most comfortable with.
On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs.
On Windows, there is for example the [http://winscp.net/ WinSCP client].
== I can't edit the files in my game directory, it looks like they are readonly. What's happening? ==
Maybe there is a maintenance operation underway.
If you don't get access back after some time (say one or two hours), please send us a mail to check.
== What is the working language on BGA studio? ==
Working language is '''English'''.
Variables and functions must be named with English words.
Comments must be written in English.
Game interface strings and game logs must be written in English.
== How can I provide translation in my language? ==
The community will translate the game in all language after the game release with the collaborative translation interface can be used to translate into other languages.
Check [[Translations]] to see how to make your game translatable.
== I updated the images in the 'img' folder of my game, but they don't show? ==
'''Concerning game_box.png, game_icon.png and publisher.png''':
You must use "Reload game box image" function from "Control Panel / Manage Games / Your game" to make your change visible.
'''Concerning other images''':
Other images used during the game are immediately available without any action.
If the images still don't show after that, please try emptying your browser cache and reloading the page.
== I added some game options / some game statistics / some game infos but they don't show? ==
When you modify one of these 3 files, you need to use the corresponding update action from "Control Panel / Manage Games / Your Game" in order we can take this information into account.
== Should I use images free from copyright? ==
If you are developing a game in the public domain, yes (or you can make your own if you feel it's better).
If you are developing a game for which we have a licence, we will usually provide art files from the publisher.
204f89bb29ebe846f92df7fb2465c3fbc5525394
Studio file reference
0
54
945
454
2013-09-30T16:29:24Z
Sourisdudesert
1
wikitext
text/x-wiki
This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment.
=== 'img' directory ===
This directory contains the images for your game (the game art).
=== gameinfos.inc.php ===
In this file you describe the meta-information for your game: game name, publisher name, number of player, game categories, etc...
=== dbmodel.sql ===
File for creating specific database tables that you will need to persist data during the game (for example a table for cards).
=== gameoptions.inc.php ===
File for describing your game options (= game variants)
=== <gamename>.action.php ===
File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions.
=== <gamename>.css ===
CSS styles specific to your game.
=== <gamename>.game.php ===
This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
=== <gamename>.js ===
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
=== <gamename>.view.php and <gamename>_<gamename>.tpl ===
Files used to set up the page layout ('view') for the game.
=== material.inc.php ===
File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants.
=== states.inc.php ===
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
=== stats.inc.php ===
File used to list statistics that you want to update during the game to be presented to players at the end of the game.
16fa2ec038a841941fbc7955f6cd2d40702d2ba7
Main game logic: yourgamename.game.php
0
86
946
837
2013-09-30T16:32:23Z
Sourisdudesert
1
/* Manage player scores and Tie breaker */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this:
<pre>
'tie_breaker_description' => totranslate("Describe here your tie breaker formula"),
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaVisibleSystemException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
c7a1c116b0b88b77bab55c2bf6aa0b5fd6243a66
Game interface stylesheet: yourgamename.css
0
96
947
832
2013-09-30T16:33:26Z
Sourisdudesert
1
wikitext
text/x-wiki
This is the CSS stylesheet of your game User Interface.
Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript.
Usually, you are using CSS to:
1°) define the overall layout of your game
(ex: place the board on the top left, place player's hand beside, place the deck on the right, ...).
2°) create your CSS-sprites:
All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly.
Example:
<pre>
Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image):
.white_token {
background-image: url('img/tokens.png');
background-position: 0px 0px;
}
.black_token {
background-image: url('img/tokens.png');
background-position: -20px 0px;
}
.token {
width: 20px;
height: 20px;
background-repeat: none;
}
</pre>
3°) ... anything else:
It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query).
This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily.
Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary.
Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them.
== Warning: using Z-index ==
You may use z-index CSS property in your game interface, but you should pay attention to the following: BGA dialogs are displayed with a z-index of 950. If you want to use z-index safely, you should use value '''lower than 900'''.
About z-index: don't forget that if you are using a z-index, your element will be displayed above all elements that do not have a z-index. So it's no use to have big z-index values: 1 is enough most of the time :)
== spectatorMode ==
When a spectator (= a player that is not part of the game) is viewing a game, the BGA framework add the CSS class "spectatorMode" to the wrapping HTML tag of your game.
This way, if you want to apply a special style to some elements of your game for spectators, you can do this in your CSS:
<pre>
.spectatorMode #your_element_id {
/* your special style */
}
</pre>
The most common usage of this is to hide some elements to spectators. For example, to hide "my hand" elements:
<pre>
.spectatorMode #my_hand {
display: none;
}
</pre>
d2ecdabf8bbe79bc9de1af33a714ff292cf0cc2d
Game art: img directory
0
89
948
458
2013-09-30T16:35:56Z
Sourisdudesert
1
/* Images loading */
wikitext
text/x-wiki
== Requested images ==
The following images are requested by BGA:
;game_box.png
* It is displayed on the main site on the game description page and when creating a table (280x280 px).
* It should be an image of a physical copy of the game box as it appears in an online shop.
* It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game.
* The background of the image must be transparent.
;game_icon.png
* It is the icon displayed in the lists of games and tables (50x50 px).
* This one should not be transparent, and shouldn't have a border (a black border will be add by BGA).
* The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title).
;publisher.png
* It is the logo of the publisher of the game, displayed on the game description page.
* The width must be 150 px. The height can be anything. The image could be transparent.
;publisher2.png (optional)
* If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one).
== Game art ==
You must upload in img directory all images of your game interface.
=== Images loading ===
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]).
=== Images format ===
You can use 3 image format while building your game interface:
;jpg images
should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load.
;png images
should be used for transparent images.
;gif images
can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful.
=== Use CSS Sprites ===
To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one.
To learn more on CSS Sprites:
* [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)].
* [[Game interface stylesheet: yourgamename.css]]
c375cbd06f058de2b6a7055ff948b6cc493d0705
949
948
2013-09-30T16:37:28Z
Sourisdudesert
1
/* Requested images */
wikitext
text/x-wiki
== Requested images ==
The following images are requested by BGA:
;game_box.png
* It is displayed on the main site on the game description page and when creating a table (280x280 px).
* It should be an image of a physical copy of the game box as it appears in an online shop.
* It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game.
* The background of the image must be transparent.
;game_icon.png
* It is the icon displayed in the lists of games and tables (50x50 px).
* This one should not be transparent, and shouldn't have a border (a black border will be add by BGA).
* The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title).
;publisher.png
* It is the logo of the publisher of the game, displayed on the game description page.
* The width must be 150 px. The height can be anything. The image could be transparent.
;publisher2.png (optional)
* If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one).
'''Important''': when you modify these images, you MUST click on "Reload game box image" from the Control Panel in order your update can be taken into account.
== Game art ==
You must upload in img directory all images of your game interface.
=== Images loading ===
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]).
=== Images format ===
You can use 3 image format while building your game interface:
;jpg images
should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load.
;png images
should be used for transparent images.
;gif images
can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful.
=== Use CSS Sprites ===
To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one.
To learn more on CSS Sprites:
* [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)].
* [[Game interface stylesheet: yourgamename.css]]
63dfdacfb94b2035891ea1876834814a7accb371
950
949
2013-09-30T16:37:41Z
Sourisdudesert
1
wikitext
text/x-wiki
== Requested images ==
The following images are requested by BGA:
;game_box.png
* It is displayed on the main site on the game description page and when creating a table (280x280 px).
* It should be an image of a physical copy of the game box as it appears in an online shop.
* It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game.
* The background of the image must be transparent.
;game_icon.png
* It is the icon displayed in the lists of games and tables (50x50 px).
* This one should not be transparent, and shouldn't have a border (a black border will be add by BGA).
* The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title).
;publisher.png
* It is the logo of the publisher of the game, displayed on the game description page.
* The width must be 150 px. The height can be anything. The image could be transparent.
;publisher2.png (optional)
* If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one).
'''Important''': when you modify these images, you MUST click on "Reload game box image" from the Control Panel in order your update can be taken into account.
== Game art ==
You must upload in img directory all images of your game interface.
=== Images loading ===
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]).
=== Images format ===
You can use 3 image format while building your game interface:
;jpg images
should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load.
;png images
should be used for transparent images.
;gif images
can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful.
=== Use CSS Sprites ===
To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one.
To learn more on CSS Sprites:
* [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)].
* [[Game interface stylesheet: yourgamename.css]]
40266cef396b2576bf69a369b35f066d285ba3c9
Game meta-information: gameinfos.inc.php
0
130
952
2013-09-30T16:45:33Z
Sourisdudesert
1
Created page with " From this file, you can edit the various meta-information of your game. Once you modified the file, don't forget to click on "Reload game informations" from the Control Pane..."
wikitext
text/x-wiki
From this file, you can edit the various meta-information of your game.
Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account.
Most information provided in this file are self-explainable. Some information, though:
* You are not allowed to set the "is_beta" to 0 before the game has been released on BGA and stabilized.
* "fast/medium/slow_additional_time": please set high values here: after the game has been released, we will lower these value to match the real game duration.
* "players": during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way.
* suggest_player_number / not_recommend_player_number: don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt.
a7f2e3b93ea9584d908256fad7ce012a25fbc445
953
952
2013-09-30T16:53:46Z
Sourisdudesert
1
wikitext
text/x-wiki
From this file, you can edit the various meta-information of your game.
Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account.
Most information provided in this file are self-explainable. Some information, though:
* You are not allowed to set the "'''is_beta'''" to 0 before the game has been released on BGA and stabilized.
* "'''fast/medium/slow_additional_time'''": please set high values here: after the game has been released, we will lower these value to match the real game duration.
* "'''players'''": during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way.
* '''suggest_player_number''' / '''not_recommend_player_number''': don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt.
== Tags ==
Any number of '''Tags''' can be attribute to your game. Tags are useful to place your game in the correct place and to give a good quick overview of what the game is about to players.
Main game category (you MUST specify one tag AND ONLY ONE from this category):
* 1: Abstract game
* 2: Casual games
* 3: For regular players
* 4: For core gamers
Other tags (you can specify any numbers of tags):
* 10: Short game (<10 minutes)
* 11: Medium length game (10 minutes to 30 minutes)
* 12: Long game (>30mn)
* 20: Awarded game (Win a prestigious award)
* 22: Prototype (This game has not been published yet)
* 23: Classic (This game is a classic from Public Domain)
* 30: 2 players (2p game / best with 2 players)
* 100: Fantasy theme
* 101: Science Fiction them
* 102: Historical theme
* 103: Adventure
* 104: Exploration
* 105: Conquest
* 106: Building
* 200: Card game (Cards plays a central role in this game)
* 201: Dice
* 202: Solo game
* 203: Worker placement
* 204: Hand management
* 205: Bluff
* 206: Tile placement
* 207: Combinations
* 208: Majority
* 209: Race
* 210: Collection
b7adfde2045949c9bb7e966a50dc3a89a4321342
976
953
2013-10-07T16:25:29Z
Sourisdudesert
1
wikitext
text/x-wiki
From this file, you can edit the various meta-information of your game.
Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account.
Most information provided in this file are self-explainable. Some information, though:
* You are not allowed to set the "'''is_beta'''" to 0 before the game has been released on BGA and stabilized.
* "'''fast/medium/slow_additional_time'''": please set high values here: after the game has been released, we will lower these value to match the real game duration.
* "'''players'''": during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way.
* '''suggest_player_number''' / '''not_recommend_player_number''': don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt.
== Tags ==
Any number of '''Tags''' can be attribute to your game. Tags are useful to place your game in the correct place and to give a good quick overview of what the game is about to players.
Main game category (you MUST specify one tag AND ONLY ONE from this category):
* 1: Abstract game
* 2: Casual games
* 3: For regular players
* 4: For core gamers
Other tags (you can specify any numbers of tags):
* 10: Short game (<10 minutes)
* 11: Medium length game (10 minutes to 30 minutes)
* 12: Long game (>30mn)
* 20: Awarded game (Win a prestigious award) (the game must have been at the '''first''' place of one the [http://boardgamegeek.com/wiki/page/Gaming_Industry_Awards# following major awards list]).
* 22: Prototype (This game has not been published yet)
* 23: Classic (This game is a classic from Public Domain)
* 30: 2 players (2p game / best with 2 players)
* 100: Fantasy theme
* 101: Science Fiction them
* 102: Historical theme
* 103: Adventure
* 104: Exploration
* 105: Conquest
* 106: Building
* 200: Card game (Cards plays a central role in this game)
* 201: Dice
* 202: Solo game
* 203: Worker placement
* 204: Hand management
* 205: Bluff
* 206: Tile placement
* 207: Combinations
* 208: Majority
* 209: Race
* 210: Collection
9a707a842ac57ac98cd686c8adb1c31d424af888
Stock
0
97
954
731
2013-09-30T16:54:40Z
Sourisdudesert
1
/* Using stock: a simple example */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
At first, don't forget to add "ebg/stock" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <==== HERE
],
</pre>
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_themeurl+'img/your_game_name/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
01488763215a10369fb58c28d5d29f666d3df21a
955
954
2013-09-30T16:55:31Z
Sourisdudesert
1
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
At first, don't forget to add "ebg/stock" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <==== HERE
],
</pre>
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_gamethemeurl+'img/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
84276d4edcefbc9680bc48c07d1d64a51b57518e
Studio
0
49
956
951
2013-09-30T17:00:44Z
Sourisdudesert
1
/* BGA Studio user guide */
wikitext
text/x-wiki
[[File:Bga_studio_small.jpg]]
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available.
== What is Board Game Arena Studio? ==
'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform.
It is open to any gamer with development skills :)
BGA Studio website:
http://en.studio.boardgamearena.com
(original announcement on BGA forum: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973)
== Discover BGA Studio in 5 presentations ==
Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you:
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game]
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena]
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance]
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines]
== How to join the BGA developer team? ==
Please see this page: [[How to join BGA developer team?]]
== Great, I'm in! ... How should I start? ==
If you didn't already, check the presentations at the top of this page to get the basics.
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.
After that, we advise you to take a peek at one or both of these two game creation tutorials:
* [[Tutorial reversi]]
* [[Tutorial gomoku]]
Then start editing files and see what happens! ;)
If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum'''].
== BGA Studio documentation ==
=== BGA Studio Framework reference ===
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.
[[Studio file reference|File structure of a BGA game]]
==== Game logic ====
* [[Main game logic: yourgamename.game.php]]
* [[Your game state machine: states.inc.php]]
* [[Game database model: dbmodel.sql]]
* [[Players actions: yourgamename.action.php]]
* [[Game material description: material.inc.php]]
* [[Game statistics: stats.inc.php]]
==== Game interface ====
* [[Game interface logic: yourgamename.js]]
* [[Game art: img directory]]
* [[Game interface stylesheet: yourgamename.css]]
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]
==== Other components ====
* [[Translations]] (how to make your game translatable)
* [[Game options and preferences: gameoptions.inc.php]]
* [[Game meta-information: gameinfos.inc.php]]
* [[Game replay]]
=== BGA Studio game components reference ===
Game components are useful tools you can use in your game adaptations.
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score).
* [[Draggable]]: a JS component to manage drag'n'drop actions.
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.
* [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned.
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
=== BGA Studio user guide ===
This part of the documentation is a user guide for the BGA Studio online development environment.
* [[Tools and tips of BGA Studio]]
* [[Practical debugging]]
* [[Studio logs]]
* [[Studio FAQ]]
== BGA Developer team organization ==
* [[Steps to create a BGA game]]
* [[Post-release phase]]
== Other resources ==
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]
[http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum]
ac77cc3aebc248727c5d63ba7c05bcfed8a8a923
Steps to create a BGA game
0
117
957
809
2013-09-30T17:04:00Z
Sourisdudesert
1
wikitext
text/x-wiki
Here's a summary of the different steps you would follow when developing a game with BGA Studio.
{| class="wikitable"
|-
! Step !! How to reach this ste?p !! What happened during the step?
|-
| Initial || [[How to join BGA developer team?]] || You can choose to join an existing team / create a new project
|-
| Assigned || You choosed a game || You can start the development of the game
|-
| Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice.
|-
| Alpha || You tell us that your development is finished || "BGA review": we are reviewing your game and check if it respects [http://fr.slideshare.net/boardgamearena/bga-studio-guidelines BGA guidelines]. If not, we will ask you (and help you) to fix them.
|-
| Private beta || We give a "go" || "Publisher review": On preproduction platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer.
|-
| Public beta || The adaptation is approved by the publiher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]].
|-
| Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]].
|}
3057282ef1dc5e90cca44ca7d9c29442ffdfe22d
Post-release phase
0
118
958
825
2013-09-30T17:10:52Z
Sourisdudesert
1
wikitext
text/x-wiki
Your game is now on BGA: congrats!
But what happened when there are some bugs to fix or when you want to optimize something?
Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below.
== Bugs reporting ==
Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum].
During days after your game has been published and from time to time, please have a look at it to check if everything is fine.
== How to submit changes? ==
There is 3 (short) steps to make your changes visible on BGA (from your Control Panel):
* Commit your changes.
* Build a new version (don't forget to do a successful commit BEFORE your build).
* Deploy your new version in production.
== What can be modified after release? ==
Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases:
===Changes that breaks the games in progress===
Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us.
Example of changes that break the games in progress:
* Changes in the database schema of the game (dbmodel.sql).
* New global variable or game option accessed during the game (if it's only used during setup, it should be safe).
* New statistic (it won't be initialized properly, so it's going to crash the game).
* Change ID of existing game states (adding new game states is fine).
Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case:
* Try to group all your updates in one version, thus we won't have to block your game several times.
* Tell us explicitly that you introduce some update that can break games in progress so we can block the game during a short time.
Note: in the near future, we will introduce the possibility for you to block/unblock a game directly from your Control Panel in order to perform all the process by yourself.
=== Updating Statistics ===
You should be careful when updating a statistics:
* If you want to add a new statistics, please refer to the paragraph above ("changes that breaks the games in progress").
* If you want to update a statistic, please update it and do not remove/create another one. Otherwise, the statistic won't keep the same ID and players will lost all the historical statistics data.
* If your game is published on BGA, please don't remove any statistics (historical data will be lost).
=== Updating string to be translated ===
When you update a string that has been marked to be translatable, please keep in mind that all current translations done by the BGA community will be lost.
Consequently, when you are about to modify a string to be translated (after release), please ask you the following questions:
* Is it just an English misspelling? In this case, it is better to fix the English translation of the string than the original string to be translated.
* Has the meaning of the string changed? If yes, you HAVE to change the original string in order to invalidate all translations that has been done already.
* Is there a similar string already used elsewhere in my game? In this case, you'd better use it again to enjoy immediately all translations already available.
===Major changes===
If you do some major changes to your game like:
* Introducing a new expansion.
* Major code rewriting/refactoring.
... please tell us. In this case, we can:
* Make your game back from "gold" to "public beta", to incite player to report bugs.
* And eventually, publish a news about it :)
860172b542fdcbafd19c16c6a60b8007a7c77266
BGA Game licenses
0
131
959
2013-09-30T19:38:22Z
Sourisdudesert
1
Created page with " == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this boar..."
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== What if I start developing a game that is not on the list below? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
Important: you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
You should take into account the fol
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
0:
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
1:
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher:
_ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
_ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
_ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
2:
Read the publisher list below to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
3:
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
4:
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
695cb0256a099b6554c86258e0822172848a611f
960
959
2013-09-30T19:38:48Z
Sourisdudesert
1
/* What if I start developing a game that is not on the list below? */
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== What if I start developing a game that is not on the "Available licences"? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
Important: you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
You should take into account the fol
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
0:
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
1:
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher:
_ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
_ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
_ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
2:
Read the publisher list below to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
3:
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
4:
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
93bf4d69ac7675fd10a26554fcdbc8beae355543
961
960
2013-09-30T19:39:27Z
Sourisdudesert
1
/* Wow, I WANT to develop a game on this list! */
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== What if I start developing a game that is not on the "Available licences"? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
Important: you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
You should take into account the fol
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
0:
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
1:
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher:
_ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
_ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
_ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
2:
Read the publisher list below to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
3:
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
4:
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
7abedae86b4ee8ee613db9c3c10357521b22c3ae
962
961
2013-09-30T19:39:56Z
Sourisdudesert
1
/* What has to be done to add a game on this list? */
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== What if I start developing a game that is not on the "Available licences"? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
'''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
You should take into account the fol
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
0:
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
1:
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher:
_ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
_ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
_ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
2:
Read the publisher list below to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
3:
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
4:
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
c783045c457de98285b6e6366084d147ad7cf7ee
963
962
2013-09-30T19:53:15Z
Sourisdudesert
1
/* I want my prototype/unpublished game on BGA */
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== What if I start developing a game that is not on the "Available licences"? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
'''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
This is possible, BUT most of the time, we consider this is a bad idea for the following reasons:
* if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it.
* as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA.
* we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization.
So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below:
* the game is going to be published in the near future.
* the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...).
* you want to test a game with a big number of players to finalize some minor things ("balance").
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
0:
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
1:
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher:
_ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
_ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
_ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
2:
Read the publisher list below to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
3:
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
4:
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
19303f4c227bf19a3b897b61ee7148f3592a5d7b
964
963
2013-09-30T19:54:07Z
Sourisdudesert
1
/* What if I really want to develop a particular game that is NOT on the list below? */
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== What if I start developing a game that is not on the "Available licences"? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
'''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
This is possible, BUT most of the time, we consider this is a bad idea for the following reasons:
* if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it.
* as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA.
* we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization.
So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below:
* the game is going to be published in the near future.
* the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...).
* you want to test a game with a big number of players to finalize some minor things ("balance").
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
=== 0: ===
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
=== 1: ===
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher:
_ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
_ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
_ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
=== 2: ===
Read the publisher list below to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
=== 3: ===
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
=== 4: ===
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
c63fc6b89c725461f6a5a66b986dd8c92d176159
965
964
2013-09-30T19:55:45Z
Sourisdudesert
1
/* 1: */
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== What if I start developing a game that is not on the "Available licences"? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
'''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
This is possible, BUT most of the time, we consider this is a bad idea for the following reasons:
* if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it.
* as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA.
* we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization.
So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below:
* the game is going to be published in the near future.
* the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...).
* you want to test a game with a big number of players to finalize some minor things ("balance").
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
=== 0: ===
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
=== 1: ===
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher.
To find the original publisher:
* check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
* check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
* very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
=== 2: ===
Read the publisher list below to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
=== 3: ===
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
=== 4: ===
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
b6c44a94b871bfa92a9307663bda5a41f4d0ed7b
966
965
2013-09-30T19:56:30Z
Sourisdudesert
1
/* 2: */
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== What if I start developing a game that is not on the "Available licences"? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
'''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
This is possible, BUT most of the time, we consider this is a bad idea for the following reasons:
* if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it.
* as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA.
* we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization.
So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below:
* the game is going to be published in the near future.
* the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...).
* you want to test a game with a big number of players to finalize some minor things ("balance").
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
=== 0: ===
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
=== 1: ===
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher.
To find the original publisher:
* check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
* check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
* very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
=== 2: ===
Read the publisher list from the "available licence" page to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
=== 3: ===
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
=== 4: ===
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
26c04bdf3793ee0fa5b163639693fe822930ff25
967
966
2013-09-30T19:57:56Z
Sourisdudesert
1
wikitext
text/x-wiki
== What is a "licence" ==
Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website.
== Are all games on BGA licenced by their respective right owners? ==
Yes.
== Where can I find available games licences ==
http://en.studio.boardgamearena.com/#!page/availablelicences
== What if I start developing a game that is not on the "Available licences"? ==
We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process.
Exception: games on the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Cool :)
But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What has to be done to add a game on this list? ==
The right owners has to give an licence/authorization to BGA.
Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract.
'''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below).
== Why all best-sellers games I love are not on that list? ==
As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA.
So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this".
We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want my prototype/unpublished game on BGA ==
This is possible, BUT most of the time, we consider this is a bad idea for the following reasons:
* if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it.
* as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA.
* we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization.
So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below:
* the game is going to be published in the near future.
* the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...).
* you want to test a game with a big number of players to finalize some minor things ("balance").
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most asked question, to please follow the instructions:
=== 0: ===
In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it?
Continue to 1.
=== 1: ===
At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher.
To find the original publisher:
* check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish).
* check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time.
* very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher.
Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome.
Continue to 2
=== 2: ===
Read the publisher list from the "available licence" page to check if BGA already work with this publisher.
If YES, continue to 3.
If NO, continue to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
=== 3: ===
Is there already a game licenced by this publisher that has to be developed?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization!
=== 4: ===
We never worked with this publisher before.
If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :)
If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation.
Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA.
04a8e9ded7e7fa61ef6e9a9a76858da7938e4856
970
967
2013-10-01T20:52:40Z
Een
3
wikitext
text/x-wiki
== What's a "license" ==
Almost all games on the Board Game Arena platform are adaptations of existing commercial "real" board games. In order to host an adaptation of one of these board games on a website, the copyright owners must first grant a license/authorisation to this website.
== Are all games on BGA licensed by their respective copyright owners? ==
Yes, for all games that are not in the public domain, BGA has been granted an authorisation to create and host an online version.
== Where can I find a list of games for which a license has already been granted? ==
[http://en.studio.boardgamearena.com/#!page/availablelicences Check the list of available licenses]
(NB: this page is restricted to developers registered in BGA studio. You'll need to enter your BGA studio credentials to access it)
== What if I start developing a game that is not on the "Available licences" list? ==
We allow developers to start any project in the Studio. But when you submit your project to go live on BGA, it will be rejected during the review process if BGA doesn't hold a proper license for the game.
Exception: games in the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Great! :)
But before creating a new project, please takes some seconds to check that someone is not already developing this game. If it is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What needs to be done to add a game on this list? ==
The copyright owners have to give an license/authorisation to BGA.
Publishers do not have to pay anything to BGA for this, they just need to give their "go". Most of the time, publishers want to have a formal agreement and we sign a contract with them.
'''Important''': you CAN'T take the initiative to ask a license authorization on behalf of BGA, because the authorisation has to be granted to BGA (read more below).
== Why aren't all the best-selling games that I love on that list? ==
As you can imagine, the more popular a game is, the most difficult it can be to get an agreement to host this game on BGA.
So if you are thinking about a very popular game that is not on this list, the reason is most likely "we asked but it was not possible" and not "we didn't think of it".
We are really happy to have been able to build a very nice platform that managed to convince some of the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want to make my prototype/unpublished game available on BGA ==
This is possible, BUT most of the time, we consider this is a bad idea for the following reasons:
* if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it.
* as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes most likely won't get a big audience on BGA.
* we also advise you against developing your own game: games adaptation are better when there is a designer whose focus is on the gameplay and a developer whose focus is on the implementation.
So you definitely can develop your prototype/unpublished game on BGA, but we encourage you to think twice about it and do it only if you are in one/several of the situations below:
* the game is going to be published in the near future
* the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...)
* you want to test your game with a big number of players to fine-tune some minor things ("balance" of the game).
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most frequently asked question, so for a detailed answer please follow the white rabbit down these numbered instructions:
=== 0: ===
In any case: please, do not contact publishers without asking us before. Just put yourself in the shoes of a game publisher who just published a popular game: what would you think if you received 40 emails from 40 developers speaking about some "BGA platform" and wanting to build an adaptation on it?
Proceed to 1.
=== 1: ===
First, you should determine who is the owner of the digital rights of the game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because very often board games are translated and published in different countries by a local publisher.
To find the original publisher:
* check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably Polish).
* check the copyright notice at the end of the rules, where the original publisher is mentioned almost every time.
* very often, if two publishers are mentioned on a gamebox, the well-known publisher is the local publisher from your country and the other one is the original publisher.
Special case: if the game is themed with a prestigious licence (Star Wars, Lord of the Rings, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licenses owners are very restrictive, and there is 99% chance that an online adaptation on BGA would be impossible to manage.
Continue to 2.
=== 2: ===
Read the list of publishers from the "available licenses" page to check if BGA is already working with this publisher.
If YES, proceed to 3.
If NO, jump to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens that some publishers are not convinced or interested by online boardgaming and it is their right to think so. The BGA team regularly meets new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
=== 3: ===
Is there already in the list a game licensed by this publisher that is available to be developed or under development?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a license for a game, the publisher naturally expects that this game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop another game from this particular publisher, the best option for you is to help develop the game that is currently licensed and then ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we will be happy to ask the publisher for his authorisation.
=== 4: ===
We have never worked with this publisher before.
If you have already developed a game on BGA, we will be happy to contact the publisher to ask for an authorisation :)
If this is your first game on BGA, we advise you to start with a game already on the list. Why? Because unfortunately, some developers ask us to request a license, and then don't finish the development. When we ask for a license, we are more comfortable if you have already shown your ability to realise an adaptation.
Special case: if you know the publisher PERSONALLY, or have some contact there, please tell us so we can help you setup a contract allowing us to host a game adaptation on BGA.
7e176a08204233bebc4a4d93360a66c2b440a050
971
970
2013-10-01T20:54:58Z
Een
3
wikitext
text/x-wiki
== What is a "license" exactly? ==
Almost all games on the Board Game Arena platform are adaptations of existing commercial "real" board games. In order to host an adaptation of one of these board games on a website, the copyright owners must first grant a license/authorisation to this website.
== Are all games on BGA licensed by their respective copyright owners? ==
Yes, for all games that are not in the public domain, BGA has been granted an authorisation to create and host an online version.
== Where can I find a list of games for which a license has already been granted? ==
[http://en.studio.boardgamearena.com/#!page/availablelicences Check the list of available licenses]
(NB: this page is restricted to developers registered in BGA studio. You'll need to enter your BGA studio credentials to access it)
== What if I start developing a game that is not on the "Available licences" list? ==
We allow developers to start any project in the Studio. But when you submit your project to go live on BGA, it will be rejected during the review process if BGA doesn't hold a proper license for the game.
Exception: games in the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Great! :)
But before creating a new project, please takes some seconds to check that someone is not already developing this game. If it is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What needs to be done to add a game on this list? ==
The copyright owners have to give an license/authorisation to BGA.
Publishers do not have to pay anything to BGA for this, they just need to give their "go". Most of the time, publishers want to have a formal agreement and we sign a contract with them.
'''Important''': you CAN'T take the initiative to ask a license authorization on behalf of BGA, because the authorisation has to be granted to BGA (read more below).
== Why aren't all the best-selling games that I love on that list? ==
As you can imagine, the more popular a game is, the most difficult it can be to get an agreement to host this game on BGA.
So if you are thinking about a very popular game that is not on this list, the reason is most likely "we asked but it was not possible" and not "we didn't think of it".
We are really happy to have been able to build a very nice platform that managed to convince some of the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want to make my prototype/unpublished game available on BGA ==
This is possible, BUT most of the time, we consider this is a bad idea for the following reasons:
* if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it.
* as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes most likely won't get a big audience on BGA.
* we also advise you against developing your own game: games adaptation are better when there is a designer whose focus is on the gameplay and a developer whose focus is on the implementation.
So you definitely can develop your prototype/unpublished game on BGA, but we encourage you to think twice about it and do it only if you are in one/several of the situations below:
* the game is going to be published in the near future
* the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...)
* you want to test your game with a big number of players to fine-tune some minor things ("balance" of the game).
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most frequently asked question, so for a detailed answer please follow the white rabbit down these numbered instructions:
=== 0: ===
In any case: please, do not contact publishers without asking us before. Just put yourself in the shoes of a game publisher who just published a popular game: what would you think if you received 40 emails from 40 developers speaking about some "BGA platform" and wanting to build an adaptation on it?
Proceed to 1.
=== 1: ===
First, you should determine who is the owner of the digital rights of the game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because very often board games are translated and published in different countries by a local publisher.
To find the original publisher:
* check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably Polish).
* check the copyright notice at the end of the rules, where the original publisher is mentioned almost every time.
* very often, if two publishers are mentioned on a gamebox, the well-known publisher is the local publisher from your country and the other one is the original publisher.
Special case: if the game is themed with a prestigious licence (Star Wars, Lord of the Rings, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licenses owners are very restrictive, and there is 99% chance that an online adaptation on BGA would be impossible to manage.
Continue to 2.
=== 2: ===
Read the list of publishers from the "available licenses" page to check if BGA is already working with this publisher.
If YES, proceed to 3.
If NO, jump to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens that some publishers are not convinced or interested by online boardgaming and it is their right to think so. The BGA team regularly meets new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
=== 3: ===
Is there already in the list a game licensed by this publisher that is available to be developed or under development?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a license for a game, the publisher naturally expects that this game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop another game from this particular publisher, the best option for you is to help develop the game that is currently licensed and then ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we will be happy to ask the publisher for his authorisation.
=== 4: ===
We have never worked with this publisher before.
If you have already developed a game on BGA, we will be happy to contact the publisher to ask for an authorisation :)
If this is your first game on BGA, we advise you to start with a game already on the list. Why? Because unfortunately, some developers ask us to request a license, and then don't finish the development. When we ask for a license, we are more comfortable if you have already shown your ability to realise an adaptation.
Special case: if you know the publisher PERSONALLY, or have some contact there, please tell us so we can help you setup a contract allowing us to host a game adaptation on BGA.
f7fa9a78f5dd8ccffc5028a8d1ee6f5d98648d5b
972
971
2013-10-01T20:56:18Z
Een
3
moved [[BGA Game licences]] to [[BGA Game licenses]]: typo
wikitext
text/x-wiki
== What is a "license" exactly? ==
Almost all games on the Board Game Arena platform are adaptations of existing commercial "real" board games. In order to host an adaptation of one of these board games on a website, the copyright owners must first grant a license/authorisation to this website.
== Are all games on BGA licensed by their respective copyright owners? ==
Yes, for all games that are not in the public domain, BGA has been granted an authorisation to create and host an online version.
== Where can I find a list of games for which a license has already been granted? ==
[http://en.studio.boardgamearena.com/#!page/availablelicences Check the list of available licenses]
(NB: this page is restricted to developers registered in BGA studio. You'll need to enter your BGA studio credentials to access it)
== What if I start developing a game that is not on the "Available licences" list? ==
We allow developers to start any project in the Studio. But when you submit your project to go live on BGA, it will be rejected during the review process if BGA doesn't hold a proper license for the game.
Exception: games in the public domain are of course not concerned.
== Wow, I WANT to develop a game on this list! ==
Great! :)
But before creating a new project, please takes some seconds to check that someone is not already developing this game. If it is the case, maybe you can propose to join the project?
[http://en.studio.boardgamearena.com/#!projects Check the list of current projects]
== What needs to be done to add a game on this list? ==
The copyright owners have to give an license/authorisation to BGA.
Publishers do not have to pay anything to BGA for this, they just need to give their "go". Most of the time, publishers want to have a formal agreement and we sign a contract with them.
'''Important''': you CAN'T take the initiative to ask a license authorization on behalf of BGA, because the authorisation has to be granted to BGA (read more below).
== Why aren't all the best-selling games that I love on that list? ==
As you can imagine, the more popular a game is, the most difficult it can be to get an agreement to host this game on BGA.
So if you are thinking about a very popular game that is not on this list, the reason is most likely "we asked but it was not possible" and not "we didn't think of it".
We are really happy to have been able to build a very nice platform that managed to convince some of the most prestigious publishers to host their games here, but of course we can't convince -everyone-.
== I want to make my prototype/unpublished game available on BGA ==
This is possible, BUT most of the time, we consider this is a bad idea for the following reasons:
* if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it.
* as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes most likely won't get a big audience on BGA.
* we also advise you against developing your own game: games adaptation are better when there is a designer whose focus is on the gameplay and a developer whose focus is on the implementation.
So you definitely can develop your prototype/unpublished game on BGA, but we encourage you to think twice about it and do it only if you are in one/several of the situations below:
* the game is going to be published in the near future
* the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...)
* you want to test your game with a big number of players to fine-tune some minor things ("balance" of the game).
== What if I really want to develop a particular game that is NOT on the list below? ==
This is the most frequently asked question, so for a detailed answer please follow the white rabbit down these numbered instructions:
=== 0: ===
In any case: please, do not contact publishers without asking us before. Just put yourself in the shoes of a game publisher who just published a popular game: what would you think if you received 40 emails from 40 developers speaking about some "BGA platform" and wanting to build an adaptation on it?
Proceed to 1.
=== 1: ===
First, you should determine who is the owner of the digital rights of the game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because very often board games are translated and published in different countries by a local publisher.
To find the original publisher:
* check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably Polish).
* check the copyright notice at the end of the rules, where the original publisher is mentioned almost every time.
* very often, if two publishers are mentioned on a gamebox, the well-known publisher is the local publisher from your country and the other one is the original publisher.
Special case: if the game is themed with a prestigious licence (Star Wars, Lord of the Rings, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licenses owners are very restrictive, and there is 99% chance that an online adaptation on BGA would be impossible to manage.
Continue to 2.
=== 2: ===
Read the list of publishers from the "available licenses" page to check if BGA is already working with this publisher.
If YES, proceed to 3.
If NO, jump to 4.
However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens that some publishers are not convinced or interested by online boardgaming and it is their right to think so. The BGA team regularly meets new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone.
=== 3: ===
Is there already in the list a game licensed by this publisher that is available to be developed or under development?
If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a license for a game, the publisher naturally expects that this game will be developed and published online. So we develop and publish a game before asking for another.
If you really want to develop another game from this particular publisher, the best option for you is to help develop the game that is currently licensed and then ask us to request the game you'd like to develop.
If NO: just ask us which game you want to develop and we will be happy to ask the publisher for his authorisation.
=== 4: ===
We have never worked with this publisher before.
If you have already developed a game on BGA, we will be happy to contact the publisher to ask for an authorisation :)
If this is your first game on BGA, we advise you to start with a game already on the list. Why? Because unfortunately, some developers ask us to request a license, and then don't finish the development. When we ask for a license, we are more comfortable if you have already shown your ability to realise an adaptation.
Special case: if you know the publisher PERSONALLY, or have some contact there, please tell us so we can help you setup a contract allowing us to host a game adaptation on BGA.
f7fa9a78f5dd8ccffc5028a8d1ee6f5d98648d5b
Faq
0
3
968
911
2013-10-01T19:06:03Z
Een
3
/* What do I need to play? */
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
0cda94e7386cdf0bfd3e819363c68c75b4f78c9b
Browser support
0
13
969
426
2013-10-01T19:11:36Z
Een
3
wikitext
text/x-wiki
<h3>For the best experience, we recommend:</h3>
* '''Google Chrome 10+''' [http://www.google.com/chrome Windows] [http://www.google.com/chrome?platform=mac Mac] [http://www.google.com/chrome?platform=linux Linux]
* '''Mozilla Firefox 4+''' [http://www.mozilla.org/products/firefox/ Windows] [http://www.mozilla.org/products/firefox/ Mac] [http://www.mozilla.org/products/firefox/ Linux]
Board Game Arena takes advantage of the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download or update, no plugins to install, etc.
Consequently, to play you need to use a modern web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be.
This website makes intensive use of Javascript and your browser's graphics capabilities. Thus, if you want to have the best gaming experience with Board Game Arena, you should use one of the browsers listed above. However, we officially support the following browsers:
* Google Chrome 4+
* Mozilla Firefox 3.5+
* Internet Explorer 9+
* Safari 4+
(Note: We do NOT support playing on iPads or similar tablets.)
[[Category:Help]]
8a4654e948afc3ad04edef323b0769cd8cdcae40
BGA Game licences
0
132
973
2013-10-01T20:56:18Z
Een
3
moved [[BGA Game licences]] to [[BGA Game licenses]]: typo
wikitext
text/x-wiki
#REDIRECT [[BGA Game licenses]]
a99c9debf146a8f72d9071adcdf88894fcd0b39a
Gamehelpmachiavelli
0
133
974
2013-10-03T20:53:55Z
Emanueles
3943
Created page with " == Game materials == Machiavelli is played with 2 or more french decks without using jokers. == Goal of the game == The game ends when a player plays all his cards or when t..."
wikitext
text/x-wiki
== Game materials ==
Machiavelli is played with 2 or more french decks without using jokers.
== Goal of the game ==
The game ends when a player plays all his cards or when the deck is depleted.
== Game setup ==
Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table.
== How to play ==
Each turn players can do a sequence of action, until the turn ends.
Actions:
* ''Draw a card''
The player can draw a card from the deck and his turn ends.
* ''Play cards''
Player can play cards from his hand, laying them on the table and respecting the following rules:
1) Cards on the table must always form groups that contain at least 3 cards.
2) Groups on the table must be sets or runs.
- Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣).
- Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K.
Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence).
* ''Take cards''
Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too.
Example:
Groups on the table:
3♣, 4♣, 5♣, 6♣
Q♥, Q♦, Q spades
Player's hand:
5♣, 7♣, 8♣, Q♣, J♥, K♥
Player takes the 2 groups on the table, then he plays cards creating these new groups:
3♣, 4♣, 5♣
5♣, 6♣, 7♣, 8♣
J♥, Q♥, K♥
Q♦, Q♠, Q♣
* ''Restore''
If a player took cards from the table and he is no more able to play all token cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the token cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 3 cards from the deck as penalty.
* ''Pass''
Player can pass only if he played cards and if he has no cards taken from the table in his hand.
== End of the game ==
Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand.
88b66124042dac597c46d922ef5de478b913914c
975
974
2013-10-03T21:05:48Z
Emanueles
3943
wikitext
text/x-wiki
== Game materials ==
Machiavelli is played with 2 or more french decks without using jokers.
== Goal of the game ==
The game ends when a player plays all his cards or when the deck is depleted.
== Game setup ==
Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table.
== How to play ==
Each turn players can do a sequence of action, until the turn ends.
Actions:
* ''Draw a card''
The player can draw a card from the deck and his turn ends.
* ''Play cards''
Player can play cards from his hand, laying them on the table and respecting the following rules:
1) Cards on the table must always form groups that contain at least 3 cards.
2) Groups on the table must be sets or runs.
- Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣).
- Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K.
Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence).
* ''Take cards''
Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too.
Example:
Groups on the table:
3♣, 4♣, 5♣, 6♣
Q♥, Q♦, Q spades
Player's hand:
5♣, 7♣, 8♣, Q♣, J♥, K♥
Player takes the 2 groups on the table, then he plays cards creating these new groups:
3♣, 4♣, 5♣
5♣, 6♣, 7♣, 8♣
J♥, Q♥, K♥
Q♦, Q♠, Q♣
* ''Restore''
If a player took cards from the table and he is no more able to play all token cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the token cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 3 cards from the deck as penalty.
In the BGA version the ''Restore'' action can be automatically performed clicking on a specific button. Cards token from the table are tagged with a red sign as reminder to play it before passing.
* ''Pass''
Player can pass only if he played cards and if he has no cards taken from the table in his hand.
== End of the game ==
Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand.
084c9a0a090271d58fb69df9c8e4e1e09774add0
987
975
2013-10-21T12:01:19Z
Nalafab
2897
/* How to play */
wikitext
text/x-wiki
== Game materials ==
Machiavelli is played with 2 or more french decks without using jokers.
== Goal of the game ==
The game ends when a player plays all his cards or when the deck is depleted.
== Game setup ==
Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table.
== How to play ==
Each turn players can do a sequence of action, until the turn ends.
Actions:
* ''Draw a card''
The player can draw a card from the deck and his turn ends.
* ''Play cards''
Player can play cards from his hand, laying them on the table and respecting the following rules:
1) Cards on the table must always form groups that contain at least 3 cards.
2) Groups on the table must be sets or runs.
- Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣).
- Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K.
Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence).
* ''Take cards''
Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too.
Example:
Groups on the table:
3♣, 4♣, 5♣, 6♣ / Q♥, Q♦, Q♠
Player's hand:
5♣, 7♣, 8♣, Q♣, J♥, K♥
Player takes the 2 groups on the table, then he plays cards creating these new groups:
3♣, 4♣, 5♣ / 5♣, 6♣, 7♣, 8♣ / J♥, Q♥, K♥ / Q♦, Q♠, Q♣
* ''Restore''
If a player took cards from the table and he is no more able to play all token cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the token cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 3 cards from the deck as penalty.
In the BGA version the ''Restore'' action can be automatically performed clicking on a specific button. Cards token from the table are tagged with a red sign as reminder to play it before passing.
* ''Pass''
Player can pass only if he played cards and if he has no cards taken from the table in his hand.
== End of the game ==
Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand.
d8faf700b45b7213c3d62812cebb4f362019a186
991
987
2013-11-12T21:51:15Z
Emanueles
3943
/* How to play */
wikitext
text/x-wiki
== Game materials ==
Machiavelli is played with 2 or more french decks without using jokers.
== Goal of the game ==
The game ends when a player plays all his cards or when the deck is depleted.
== Game setup ==
Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table.
== How to play ==
Each turn players can do a sequence of action, until the turn ends.
Actions:
* ''Draw a card''
The player can draw a card from the deck and his turn ends.
* ''Play cards''
Player can play cards from his hand, laying them on the table and respecting the following rules:
1) Cards on the table must always form groups that contain at least 3 cards.
2) Groups on the table must be sets or runs.
- Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣).
- Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K.
Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence).
* ''Take cards''
Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too.
Example:
Groups on the table:
3♣, 4♣, 5♣, 6♣ / Q♥, Q♦, Q♠
Player's hand:
5♣, 7♣, 8♣, Q♣, J♥, K♥
Player takes the 2 groups on the table, then he plays cards creating these new groups:
3♣, 4♣, 5♣ / 5♣, 6♣, 7♣, 8♣ / J♥, Q♥, K♥ / Q♦, Q♠, Q♣
* ''Restore''
If a player took cards from the table and he is no more able to play all token cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the token cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 1 cards from the deck and pass. In case player is not able to restore, the other players will help him to do it and then he must draw 3 cards as penalty.
NOTE WELL: In the BGA version cards token from the table are tagged with a red sign as reminder to play it before passing. '''The ''Restore'' action can be automatically performed clicking on a specific button and player receive 1 card from the deck'''. 3 cards penalty is not considered.
* ''Pass''
Player can pass only if he played cards and if he has no cards taken from the table in his hand.
== End of the game ==
Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand.
ff889e5ec7853a9c7602e22ae96a6b0981540983
Gamehelptokaido
0
134
977
2013-10-11T13:39:13Z
Nikos messis
4024
Created page with "- if you enter a panorama space,either pick that panorama or pick a cherry tree worth 2 points and 1 coin - if you enter a hot spring space,either pick the hot spring or pay 1..."
wikitext
text/x-wiki
- if you enter a panorama space,either pick that panorama or pick a cherry tree worth 2 points and 1 coin
- if you enter a hot spring space,either pick the hot spring or pay 1 coin to pick a bath house tile worth 4 points
- if you enter a souvenir shop,either buy souvenir as usual or get 1 legendary item instead,there are 6 items of 3 kinds,type 1 is worth 1 point for every souvenir and cost 1 coin,type 2 cost 2 coin and count as a family of his own (so if you have a full set already it's worth 9 point) and type 3 give cost 3 coins and give you 8 points straight
- if you enter a farm you can go instead to a gambling house,bet 2 coins and throw a dice... the dice is either 0x 1x 2x 3x or 4x so you either lose 2 coins,gain 0 coins,gain 2 coin,gain 4 coin or gain 6 coins
- if you enter a temple you can pay 1 coin for an amulet of your choice,amulet effect include
1) if you get the lead,get another turn
2) get a free meal
3) get both choice when you enter a space
4) throw the gamble dice and get coin equal to the value
5) get to a space occupied by another player
6) coin spent on an item go to the temple instead (you still get the item)
- if you enter an encounter space you can get a caligraphy item instead which scores point at the end of the game depending on how you play, these include
1) score 3 point for every skipped meal
2) score 2 point for every coin unspent you have in the end
3) score 3 point for every completed panorama and 1 point for every cherry tree
4) score 2 point per legendary item and 1 point for every souvenir
5) score 6 point if you are the last to arrive at the final inn,4 point if you are the second to last player and 2 point in the other case's
6) score 2 point per accomplishment and 1 point for every caligraphy item
to complete it all there are 6 new travelers
1) the yakuza - 5 coins - everytime he arrives on one of the three inn he can bet a single coin to the gambling house
2) the gourmet - 2 coins - he scores point equal to the price of the meal he eats
3) the old lady - 4 coins - when she stops on an encounter space, she can get both the encounter AND the caligraphy item
4) the superstitious woman - 4 coins - when she stops on a temple space,she can both donate coin to the temple AND buy an amulet
5) the kid - 3 coins - when he arrives on one of the three inn he gets a free souvenir
6) the souvenir seller - 0 coins - when he stops at a panorama he gets one cointeasel
Written by teasel
8ca5663754ea3bc364dde6dadccb5f7c673cc64f
981
977
2013-10-17T06:46:37Z
Hofty
3828
wikitext
text/x-wiki
* if you enter a panorama space,either pick that panorama or pick a cherry tree worth 2 points and 1 coin
* if you enter a hot spring space,either pick the hot spring or pay 1 coin to pick a bath house tile worth 4 points
* if you enter a souvenir shop,either buy souvenir as usual or get 1 legendary item instead,there are 6 items of 3 kinds,type 1 is worth 1 point for every souvenir and cost 1 coin,type 2 cost 2 coin and count as a family of his own (so if you have a full set already it's worth 9 point) and type 3 give cost 3 coins and give you 8 points straight
* if you enter a farm you can go instead to a gambling house,bet 2 coins and throw a dice... the dice is either 0x 1x 2x 3x or 4x so you either lose 2 coins,gain 0 coins,gain 2 coin,gain 4 coin or gain 6 coins
* if you enter a temple you can pay 1 coin for an amulet of your choice,amulet effect include
*# if you get the lead,get another turn
*# get a free meal
*# get both choice when you enter a space
*# throw the gamble dice and get coin equal to the value
*# get to a space occupied by another player
*# coin spent on an item go to the temple instead (you still get the item)
* if you enter an encounter space you can get a caligraphy item instead which scores point at the end of the game depending on how you play, these include
*# score 3 point for every skipped meal
*# score 2 point for every coin unspent you have in the end
*# score 3 point for every completed panorama and 1 point for every cherry tree
*# score 2 point per legendary item and 1 point for every souvenir
*# score 6 point if you are the last to arrive at the final inn,4 point if you are the second to last player and 2 point in the other case's
*# score 2 point per accomplishment and 1 point for every caligraphy item
* to complete it all there are 6 new travelers
*# the yakuza - 5 coins - everytime he arrives on one of the three inn he can bet a single coin to the gambling house
*# the gourmet - 2 coins - he scores point equal to the price of the meal he eats
*# the old lady - 4 coins - when she stops on an encounter space, she can get both the encounter AND the caligraphy item
*# the superstitious woman - 4 coins - when she stops on a temple space,she can both donate coin to the temple AND buy an amulet
*# the kid - 3 coins - when he arrives on one of the three inn he gets a free souvenir
*# the souvenir seller - 0 coins - when he stops at a panorama he gets one coin
a46e8ef670d710022e52d42cb42129d1c576b1b8
984
981
2013-10-18T17:43:11Z
Hofty
3828
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
: * Shokunin - one Souvenir
: * Annaibito - one Panorama
: * Samurai - 3 points
: * Kuge - 3 coins
: * Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
: * The first Souvenir in a set is worth 1 point.
: * The second Souvenir in a set is worth 3 points.
: * The third Souvenir in a set is worth 5 points.
: * The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
: * A traveler cannot taste the same culinary specialty twice during his journey.
: * A traveler can never purchase more than one Meal card per Inn.
: * A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the achievement cards (Gourmet, Collector, Bather, Chatterbox) to the appropriate travelers.
----
'''(Extracted from the english rule book)'''
f3bab9bef4594b16c6a61ddb881d33b21c87d290
997
984
2013-12-04T03:54:49Z
Ched
4183
/* Fix up bulleted lists. */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the achievement cards (Gourmet, Collector, Bather, Chatterbox) to the appropriate travelers.
----
'''(Extracted from the english rule book)'''
9182c3f8aafc47e083dba6b17ff2727a22afddc5
998
997
2013-12-04T04:11:48Z
Ched
4183
/* Added more information about the achievement cards. */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
e646fd159fcc1f219ba3be4e8385441df42ddaf9
Gamehelptzolkin
0
129
978
923
2013-10-15T22:12:51Z
Firstbass
4055
/* Food Day */
wikitext
text/x-wiki
== '''For Each Round''' ==
- Each player takes their turn, going around the table
- On a food day, feed your workers and take your rewards
- Advance the Calendar
== '''Player turn''' ==
- '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple)
- '''Either place workers OR pick up workers'''
-- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers
-- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either
--- Use the action where your worker was standing
--- Use a lower action on the wheel from where your worker was standing(if not
standing on a free action space,pay 1 corn for each step back)
--- Do nothing.
== '''Food Day''' ==
-'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for.
-- For each worker not fed, you lose 3 points
-'''Take Rewards'''
--''Middle of Age (Brown days)''
--- Receive items shown on the left edge of temples from step you are on and all steps below
-- ''End of Age (Teal Days)''
--- Remove all Age 1 buildings and fill spaces with Age 2 buildings/
--- Receive points shown on the right edge of temples for the step you are on.
--- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus.
== '''Advance the Calendar''' ==
If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day.
Otherwise:
- The worker on the Starting Player space returns to the player
-- If this person was not the starting player, they take the starting player marker.
-- If they were the starting player, the starting player marker is moved to the player on his left
- Advance the Tzolk'in Gear one day.
- The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears.
-- If you use this option, flip your board to dark side up.
-- This does not avoid food days.
23abb93a403f6d112973adff7fc438db52a7ac31
About us
0
6
979
158
2013-10-16T05:57:12Z
Wenleinotohou
4058
wikitext
text/x-wiki
First, we should say that we are gamers. Real, complete boardgames addicts.
We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games.
Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommend you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle).
[[Contact us]]
首先,我们认为自己是玩家。在现实生活中是从头彻尾的桌游爱好者。
由于时间,地域或者社区环境的原因有一些玩家不能在现实中游戏,这成为我们设计BGA的原因。我们希望借电脑游戏和桌面游戏这两者的精华,给玩家提供崭新的体验。
即使我们的目标是提供高质量的在线游戏,我们仍然相信享受桌游最好的方式是和朋友围在一张现实的桌子旁。这也是为什么我们建议您购买BGA上的桌游的实体版本。另一个原因很好理解,每份卖出的游戏可以给作者和编辑者带来收入。(...结果让我们回到了一开始的游戏方式)
d7b0f542a6b2f75173e2553721b533b3750e192a
Studio back-office
0
56
980
391
2013-10-16T08:54:43Z
Sourisdudesert
1
wikitext
text/x-wiki
'''IMPORTANT''': the Studio back-office is now '''DEPRECATED'''. Most of its functionalities are now accessible from "Control Panel / Manage Games / Your games".
You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access.
Here is a list and description of the links and functions in this back-office.
Click on a menu to display its content.
=== Documentation ===
Contains links to this wiki, the development forum and the bugs forum.
=== Database ===
Contains a link to the Studio database administration tool (PHPMyAdmin).
Your login / password for this tool is the same as for your SFTP access.
('''DEPRECATED''': now you can access to your game database with the link "Game Database" at the bottom of your game page).
=== Sources ===
Contains a form for committing your sources to the BGA repository.
* Game name field should contain the name of your game (lower case, no space). Ex: puertorico
* Comment field should contain your commit comment describing changes to the code since your last commit.
You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack.
('''DEPRECATED''': now this function is available from your Control Panel).
=== Logs ===
Gives you a web based access to the studio server logs.
; Current table error log
: main log of interest to you while developing, it contains the error happening at the table you are currently playing at.
('''DEPRECATED''': now you can access this log with the coreesponding link at the bottom of your game page).
; Current table request logs
: this log traces all the actions happening at the table you are currently playing at.
('''DEPRECATED''': now you can access this log with the coreesponding link at the bottom of your game page).
; Javascript error log
: this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly.
('''DEPRECATED''': you should use your Javascript console / Firebug plugin to do this).
; Gameserver error log
: this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file.
('''DEPRECATED''': errors during the game setup appears now directly in a red error message during your "Express start").
; HTTP error log
: this log traces the web server errors. This is useful to look at PHP syntax errors and warnings.
('''DEPRECATED''': errors now appear directly in a red message during the game).
Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in.
You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more.
ffcb9ffc3be270bfd19b8f277d8d4d1c4029e27c
Gamehelptimemasters
0
135
982
2013-10-17T17:40:54Z
Sigmund3
4072
Time Masters Rules
wikitext
text/x-wiki
Phases of the game:
1)Timer phase
If at the beginning of the turn you have a full timer, you must choose to either:
- activate it: in which case the timer and all the cards used to delay it are discarded. The spells on it remain in the Timer area and you must play them until the end of turn.
- delay it: in which case you must put a card from your hand, with the card back showing, on that timer. If you have a card on a timer you will replenish your hand until you have one card less, such as 4 cards instead of 5. Two cards to delay the timer mean 3 card in your hand maximum and so on.
If at the start of your turn you have a timer that is full, even if you pass the turn to replenish all your Ke, you must put a card from your hand to delay it.
2)Main phase:
You may play Spells, Focus or Timers and also Spells that are on active timers.
3)Access spheres Phase
You may take cards from the Spheres of Consciousness depending on the number of spells played during the turn. These new cards go directly in your hand. You can't choose to draw from the same sphere during the same turn.
One spell and you can draw from the first level, two and you can draw from the second and so on. Starting with the third spell you can combine and choose, a first and second level spell.
It is possible to take the second card from a level, which is not revealed. For this you must pay an extra cost. For example, to take the second card from the second level, you must play three spells.
4)Closing Phase
Discard all your played spells and replenish your hand until you have 5 cards, or less if you have chosen to delay timers.
End of game
The game finishes when 2 of the 5 spheres are empty, or more exactly at the end of turn of the player who draws the card that makes it happen. The players score points such that a card of gives an amount of points equal to the level it belongs. In case of equality the player with the highest amount of Ke wins.
f94cac307666332fc62671acdcba9b87c505bc77
983
982
2013-10-18T05:00:56Z
Jamie ca
4076
wikitext
text/x-wiki
Phases of the game:
1)Timer phase
If at the beginning of the turn you have a full timer, you must choose to either:
- activate it: in which case the timer and all the cards used to delay it are discarded. The spells on it remain in the Timer area and you must play them until the end of turn.
- delay it: in which case you must put a card from your hand, with the card back showing, on that timer. If you have a card on a timer you will replenish your hand until you have one card less, such as 4 cards instead of 5. Two cards to delay the timer mean 3 card in your hand maximum and so on.
If at the start of your turn you have a timer that is full, even if you pass the turn to replenish all your Ke, you must put a card from your hand to delay it.
2)Main phase:
You may play Spells, Focus or Timers and also Spells that are on active timers.
3)Access spheres Phase
You may take cards from the Spheres of Consciousness depending on the number of spells played during the turn. These new cards go directly in your hand. You can't choose to draw from the same sphere during the same turn.
One spell and you can draw from the first level, two and you can draw from the second and so on. Starting with the third spell you can combine and choose, a first and second level spell.
It is possible to take the second card from a level, which is not revealed. For this you must pay an extra cost. For example, to take the second card from the second level, you must play three spells.
4)Closing Phase
Discard all your played spells and replenish your hand until you have 5 cards, or less if you have chosen to delay timers.
End of game
The game finishes when 2 of the 5 spheres are empty, or more exactly at the end of turn of the player who draws the card that makes it happen. The players score points such that a card of gives an amount of points equal to the level it belongs. In case of equality the player with the highest amount of Ke wins.
c5849fb07b0191de069bfcac949cda5e27d07595
Gamehelpchinagold
0
136
985
2013-10-19T12:15:21Z
Elisha
2997
Created page with "Hi!"
wikitext
text/x-wiki
Hi!
c0a0ad26a634840c67a210fefdda76577b03a111
Game art: img directory
0
89
986
950
2013-10-20T20:23:41Z
Sourisdudesert
1
/* Requested images */
wikitext
text/x-wiki
== Requested images ==
The following images are requested by BGA:
;game_box.png
* It is displayed on the main site on the game description page and when creating a table (280x280 px).
* It should be a 3D image of a physical copy of the game box as it appears in an online shop.
* It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game.
* The background of the image must be transparent.
* If you don't have a 3D version of the game box, you can use the following website to create one: http://www.3d-pack.com/
;game_icon.png
* It is the icon displayed in the lists of games and tables (50x50 px).
* This one should not be transparent, and shouldn't have a border (a black border will be add by BGA).
* The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title).
;publisher.png
* It is the logo of the publisher of the game, displayed on the game description page.
* The width must be 150 px. The height can be anything. The image could be transparent.
;publisher2.png (optional)
* If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one).
'''Important''': when you modify these images, you MUST click on "Reload game box image" from the Control Panel in order your update can be taken into account.
== Game art ==
You must upload in img directory all images of your game interface.
=== Images loading ===
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]).
=== Images format ===
You can use 3 image format while building your game interface:
;jpg images
should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load.
;png images
should be used for transparent images.
;gif images
can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful.
=== Use CSS Sprites ===
To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one.
To learn more on CSS Sprites:
* [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)].
* [[Game interface stylesheet: yourgamename.css]]
a3689edf2cf06b2f1687bc4d17adaeaf8a23ff3b
Game interface logic: yourgamename.js
0
88
988
902
2013-10-27T20:30:47Z
Vaanatomic
2276
/* Players input */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ).play();
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
4cf3443c514462554d9e6824a05bc2c286383728
Gamehelphawaii
0
34
989
425
2013-11-05T16:44:26Z
Uss wampanoag
4200
/* Game-End VP's: */ obvious error, kahunas instead of tikis
wikitext
text/x-wiki
Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. There are five rounds and you get a decreasing amount of resources each round with which to acquire place tiles. Its a many-paths-to-victory kind of game. (It has been described as Stone Age without the dice).
There are three kinds of resources:
1) Feet - let you move around the board, or travel to the islands or go to the cove to catch fish.
2) Clam shells - let you buy place tiles from the board
3) Fruit - can be used in place of feet or clam shells in all-or-nothing fashion. If you substitute for feet, you must substitute the entire moving cost. If you substitute for clams, you must substitute the entire purchase price.
Moving: Your chieftains start at the beach and it costs nothing to return there from the board. Each movement in from the beach costs one foot. Moving up, down, right, left or diagonal on the board costs one foot per space. Staying on a space costs one foot.
To go to the islands, you use your boats and feet. The closest island costs three feet and the farthest costs six. You have to have the feet as well as the space on the boats for the feet. You get an immediate victory point bonus for going to the islands but you do not get a price token (more about that later). Also, you get the level 2 version of whatever place tile or item you are getting on the islands.
For instance, to go to the six foot island, you would need either:
A) two three-feet boats and six feet resources or
B) you would need the four-foot boat (which comes with a prepaid foot) and the two-foot boat as well as five feet resources. That is the advantage of the pre-paid foot on the four-foot boat.
== Purchasing: ==
To buy some thing from the board: Select the price token (round colored circle with number inside) on the space with the place tile or item you want. If there is more than one place tile available on that space, you will be given a choice of which one you want. The movement cost will be in feet and the purchase price will be in clam shells but you can substitute either or both with fruit if you have it. You gain the price token for the round. There must be an available price token in order to purchase something from that space.
You can pay double to get the level 2 version, which for most tiles is double effect.
You place it in the village (row) of your choice. You must be able to place it in order to purchase it.
A) You can only have one of each type of place tile in each village. For instance, you cannot have a foot (1) hut and a foot (2) hut in the same village but you can have a coconut fruit (1) tree and a breadfruit (2) tree in the same village.
B) You can have only one god in each village. You can only have one of each type of god in your whole kingdom and the god vp effects are kingdom-wide.
B) Each village must begin with a hut. The huts have a picture of a hut on them: foot hut, clam hut, spear hut, exchange hut, and long hut.
'''
== Resources ==
'''
== Base reources ==
Base resources are on the round indicator. They decrease with each succeeding round. Everyone gets the base resources at the beginning of the round. Any unused resources can be used in the next round.
== In-play resource bonuses ==
*The third, fourth and fifth villages give you 1, 2 and 3 clams respectively when you purchase Kahunas (Hawaiian priests) for them.
*When you purchase for your kingdom the second, third and fourth Tikis, you are granted 1, 2, and 3 feet, respectively.
*One or two of the island treasures are four fruit resources.
== Resource Generators: == generate resources at the beginning of the next round.
*Fruit level ones - one fruit
*Fruit level twos - two fruit
*Clam hut level one - one clam
*Clam hut level two - two clams
*Foot hut level one - one foot
*Foot hut level two - two feet
*Irrigation level two - one resource of your choice
*Ku god - level one and two - one foot
*Kane god level one - one clam
*Kane god level two - two clams
== Converter huts ==
Whenever you spend resources, a level 1 converter hut allows you to substitute one resource of your choice. So, for instance, you could move one space and buy something that has four price token on it with four fruit for the token and one clamshell being substituted for the one foot movement. Another example, you could go to the first island for two feet and one clamshell using a level 1 boat. The converter level 2 hut is the same but with any two resources.
'''== Victory Points =='''
== In-play VP's: ==
*Going to the islands gives you a vp bonus.
*Some of the treasures on the islands are 5 vp's.
*Spear huts and the Ku god give you a bonus whenever you take a price token with crossed spears. Level 1 is 1 pt. bonus, Level 2 is two pt. bonus.
== Round-End VP's: ==
There is a large sheild on the round indicator at the bottom. If the sum of price tokens and fish are greater than the number on the sheild, then you get a bonus. There is a large bonus for the player with highest sum score, a moderate bonus for the second highest and a token bonus for everyone else whose sum was greater than the sheild. Surfer place tiles lower the sheild value for qualifying for the bonus but surfers do not contribute to your sum when comparing to other players.
Lono god level 1 gives you 2 vp's if you qualify for the bonus, and Lono god level 2 gives you 4 vp's if you qualify for the bonus
== Game-End VP's: ==
A) Each village whose size does not extend to the Tikis (rightmost place tile of a row must intersect with the leftmost column of a Tiki) is ignored for end-game scoring - its place tiles do not count and neither does its Kahuna. The villages below it are not affected - each village must reach the leftmost Tiki independently.
B) The Kahunas on the first, second, third, fourth and fifth villages scores the player five, five, ten, ten and fifteen points respectively.
B) A hula dancer in a village scores one point for each place tile in her village including herself. A level 2 hula dancer scores two points instead of one for each place tile in her village including herself.
C) Irrigation gives you pts for each type of fruit you have in that particular village: Breadfruit, guava, coconuts and bananas.
D) The Long Hut level 2 is worth five points. The long hut level one just takes up space making it easier to reach the Kahunas but does not, itself, score points.
E) The Laka god in your kingdom scores one pt for each fruit symbol on your place tiles in all of the villages which is the whole kingdom. Laka god level 2 scores two points for each fruit symbol.
F) Kanaloa god scores two pts for each boat and each surfer on all the villages in the kingdom. Kanaloa 2 scores 4 pts for each boat and surfer.
dd6fa6c5e9dd532aa9d7d11b65d0b8fbcfcc2eeb
Gamehelpjumpgate
0
137
990
2013-11-09T07:08:53Z
Chazm
3718
Initilal reference card info
wikitext
text/x-wiki
Jump Gate
== Turn Reference ==
Take two actions on your turn. You may take the same action twice.
Fly ... to a neighboring planet.
Jump ... to another more distant planet.
Scan ... your current planet if it has any face-down resources.
Land & Claim ... your current planet if it has no face-down resources and is unclaimed.
Harvest ... 1 reource you marked with a Scan, or 1 unmarked resource at a planet with all face-up resources.
Research ... refill your hand up to 5 cards. You may discard any number of cards before refilling.
== Scoring Referece ==
If there are 7 or more markers on the Black Hole, the player(s) with the most markers on the Black Hole must discard their hidden resource cards before scoring.
Otherwise, players reveal their hidden resource cards and add them to their collected resources for scoring.
Score all collected resources as explained on the resource cards.
Add 4 points for each planet claimed.
Player with the highest score wins.
c12f202940a60092b5a498dff6f39da8eaf83ca7
Gamehelparmadora
0
138
992
2013-11-12T22:15:04Z
Luckily
4242
Created page with "Nuggets Winning Moves, 2003 designed by Christwart Conrad translated by Pitt Crandlemire Whoever digs others a goldmine... For 2 - 4 players from 8 years Gam..."
wikitext
text/x-wiki
Nuggets
Winning Moves, 2003
designed by Christwart Conrad
translated by Pitt Crandlemire
Whoever digs others a goldmine...
For 2 - 4 players from 8 years
Game material
- 1 gameboard consisting of a 5x8 grid
- 35 blockers
- 8 gold mine markers showing the number of goldstrike points for that area
- 4x16 chips with different numbers
- 1 rules booklet
Idea of the game
Nuggets have been found in the Golden Valley! The gold diggers try to sell their claims to the big mining companies for as much as they can get by gathering as many Nuggets as possible. The players take on the role of prospectors and try through skillful placement of blockers to create valuable claims and then to control them with their high value chips. But the other players have not fallen on their heads and will compete for those claims quite lively, too If it all comes to naught, the claims are laid out once again. In the end, the one who walks away with the most money will be the one who bought up the most productive claims.
Set-up
The numbered stickers are stuck onto the gold mine markers and these are then placed on the board (see the illustration). Each player chooses a color and takes as many chips of that color in the appropriate value as indicated on the following table. He places these face-down in front of himself. In a 4-player game, players sitting opposite each other form a team.
Chip-distribution total 1 point 2 points 3 points 4 points 5 points
2 players, each 16 11 2 1 1 1
3 players, each 11 7 2 1 1 -
4 players, each 8 5 1 1 1 -
The Gold mine markers are placed on the gameboard as follows:
(refer to illustration in German rules)
The youngest player begins the first game. In future games, the player that lost the most recent game always starts.
Course of the game
Play goes clockwise. On his turn, a player must execute one of the following actions:
EITHER build two blockers
OR place a chip on an unoccupied space
Build two blockers
In each case, the player places a blocker on any one unoccupied line between 2 spaces. The blockers need not be placed adjacent to each other. Restriction: a player may not place a blocker such that an area of less than 4 spaces is completely enclosed. Note: it is possible that there may be several gold mine markers in an area or even none at all.
Place a chip
The player places one of his colored chips face-down on any one unoccupied space (not already containing a chip or a gold mine marker). He secretly chooses which of his numbered chips he wishes to place. Players should decide at the beginning of the game whether players will be allowed to look at their own chips after they've been played or whether they'll simply be required to remember the numbers after they've been played..
Partnership game
Partners may communicate with each other in the 4-player game but they may not do so privately; the players on the other team must be able to see and hear everything. Also, partners may not show chips to each other.
End of the game
If a player has no more chips, he may still play blockers. Also, if there are no more blockers, a player may play his chips. Whenever a player can't or chooses not to play, he may pass but he may not then play again later. Once the last player has passed, the game ends.
Scoring
All chips are turned over. For each enclosed area, each player sums the points on his chips. The points of both partners are added together in the team game. The player with most points in an area gets all the gold mine markers in that area which score points equal to their value. Areas without gold mine markers score nothing. In the event of a tie in an area, the number of goldstrike points on the marker is divided among the tied players. (Half points are awarded when appropriate.) Whoever ultimately has acquired the most goldstrike points is able to mine the most gold Nuggets and wins the game.
Variant
Once you have become familiar with the game played according to the standard set-up, you can then try placing the gold mine markers differently in later games.
1e3776191a34e20407db27058f671a61b4d3281d
994
992
2013-11-29T05:32:37Z
Stealthswor
3331
wikitext
text/x-wiki
'''Nuggets:''' Published by Winning Moves, 2003 - designed by Christwart Conrad - translated by Pitt Crandlemire
'''Players''': For 2 - 4 players from 8 years
'''Game material''':
1 gameboard consisting of a 5x8 grid, 35 blockers, 8 gold mine markers showing the number of goldstrike points for that area, 4x16 chips with different numbers, 1 rules booklet
'''Idea of the game''':
Nuggets have been found in the Golden Valley! The gold diggers try to sell their claims to the big mining companies for as much as they can get by gathering as many Nuggets as possible. The players take on the role of prospectors and try through skillful placement of blockers to create valuable claims and then to control them with their high value chips. But the other players have not fallen on their heads and will compete for those claims quite lively, too If it all comes to naught, the claims are laid out once again. In the end, the one who walks away with the most money will be the one who bought up the most productive claims.
'''Set-up''':
The numbered stickers are stuck onto the gold mine markers and these are then placed on the board (see the illustration). Each player chooses a color and takes as many chips of that color in the appropriate value as indicated on the following table. He places these face-down in front of himself. In a 4-player game, players sitting opposite each other form a team.
'''Chip-distribution''':
2 players, each 16 11 2 1 1 1
3 players, each 11 7 2 1 1 -
4 players, each 8 5 1 1 1 -
The Gold mine markers are placed on the gameboard as follows:
(refer to illustration in German rules)
The youngest player begins the first game. In future games, the player that lost the most recent game always starts.
'''Course of the game'''
Play goes clockwise. On his turn, a player must execute one of the following actions: ''EITHER'' build two blockers ''OR'' place a chip on an unoccupied space
'''Build two blockers''':
In each case, the player places a blocker on any one unoccupied line between 2 spaces. The blockers need not be placed adjacent to each other. Restriction: a player may not place a blocker such that an area of less than 4 spaces is completely enclosed. Note: it is possible that there may be several gold mine markers in an area or even none at all.
'''Place a chip''':
The player places one of his colored chips face-down on any one unoccupied space (not already containing a chip or a gold mine marker). He secretly chooses which of his numbered chips he wishes to place. Players should decide at the beginning of the game whether players will be allowed to look at their own chips after they've been played or whether they'll simply be required to remember the numbers after they've been played..
'''Partnership game''':
Partners may communicate with each other in the 4-player game but they may not do so privately; the players on the other team must be able to see and hear everything. Also, partners may not show chips to each other.
'''End of the game''':
If a player has no more chips, he may still play blockers. Also, if there are no more blockers, a player may play his chips. Whenever a player can't or chooses not to play, he may pass but he may not then play again later. Once the last player has passed, the game ends.
'''Scoring''':
All chips are turned over. For each enclosed area, each player sums the points on his chips. The points of both partners are added together in the team game. The player with most points in an area gets all the gold mine markers in that area which score points equal to their value. Areas without gold mine markers score nothing. In the event of a tie in an area, the number of goldstrike points on the marker is divided among the tied players. (Half points are awarded when appropriate.) Whoever ultimately has acquired the most goldstrike points is able to mine the most gold Nuggets and wins the game.
51ef95683b6ec3869cac679e26a50fcba8afe0e2
995
994
2013-11-29T15:32:37Z
Trzynastka
4332
wikitext
text/x-wiki
***********************************************************************************************************************************
'''''Game Nuggets is not the same as Armadora, it is only similar.'''''
Proper rules: http://pl.boardgamearena.com/link?url=http%3A%2F%2Fcdn.boardgamearena.net%2Fdata%2Fnewsimg%2FArmadora_EN.pdf&id=1228
***********************************************************************************************************************************
'''Nuggets:''' Published by Winning Moves, 2003 - designed by Christwart Conrad - translated by Pitt Crandlemire
'''Players''': For 2 - 4 players from 8 years
'''Game material''':
1 gameboard consisting of a 5x8 grid, 35 blockers, 8 gold mine markers showing the number of goldstrike points for that area, 4x16 chips with different numbers, 1 rules booklet
'''Idea of the game''':
Nuggets have been found in the Golden Valley! The gold diggers try to sell their claims to the big mining companies for as much as they can get by gathering as many Nuggets as possible. The players take on the role of prospectors and try through skillful placement of blockers to create valuable claims and then to control them with their high value chips. But the other players have not fallen on their heads and will compete for those claims quite lively, too If it all comes to naught, the claims are laid out once again. In the end, the one who walks away with the most money will be the one who bought up the most productive claims.
'''Set-up''':
The numbered stickers are stuck onto the gold mine markers and these are then placed on the board (see the illustration). Each player chooses a color and takes as many chips of that color in the appropriate value as indicated on the following table. He places these face-down in front of himself. In a 4-player game, players sitting opposite each other form a team.
'''Chip-distribution''':
2 players, each 16 11 2 1 1 1
3 players, each 11 7 2 1 1 -
4 players, each 8 5 1 1 1 -
The Gold mine markers are placed on the gameboard as follows:
(refer to illustration in German rules)
The youngest player begins the first game. In future games, the player that lost the most recent game always starts.
'''Course of the game'''
Play goes clockwise. On his turn, a player must execute one of the following actions: ''EITHER'' build two blockers ''OR'' place a chip on an unoccupied space
'''Build two blockers''':
In each case, the player places a blocker on any one unoccupied line between 2 spaces. The blockers need not be placed adjacent to each other. Restriction: a player may not place a blocker such that an area of less than 4 spaces is completely enclosed. Note: it is possible that there may be several gold mine markers in an area or even none at all.
'''Place a chip''':
The player places one of his colored chips face-down on any one unoccupied space (not already containing a chip or a gold mine marker). He secretly chooses which of his numbered chips he wishes to place. Players should decide at the beginning of the game whether players will be allowed to look at their own chips after they've been played or whether they'll simply be required to remember the numbers after they've been played..
'''Partnership game''':
Partners may communicate with each other in the 4-player game but they may not do so privately; the players on the other team must be able to see and hear everything. Also, partners may not show chips to each other.
'''End of the game''':
If a player has no more chips, he may still play blockers. Also, if there are no more blockers, a player may play his chips. Whenever a player can't or chooses not to play, he may pass but he may not then play again later. Once the last player has passed, the game ends.
'''Scoring''':
All chips are turned over. For each enclosed area, each player sums the points on his chips. The points of both partners are added together in the team game. The player with most points in an area gets all the gold mine markers in that area which score points equal to their value. Areas without gold mine markers score nothing. In the event of a tie in an area, the number of goldstrike points on the marker is divided among the tied players. (Half points are awarded when appropriate.) Whoever ultimately has acquired the most goldstrike points is able to mine the most gold Nuggets and wins the game.
00f0954786d3db52bede4c38c5d0ea55e2855d8b
999
995
2013-12-05T14:18:23Z
Trzynastka
4332
wikitext
text/x-wiki
*
'''''Game Nuggets is not the same as Armadora, it is only similar.'''''
Proper rules: http://pl.boardgamearena.com/link?url=http%3A%2F%2Fcdn.boardgamearena.net%2Fdata%2Fnewsimg%2FArmadora_EN.pdf&id=1228
*
'''Nuggets:''' Published by Winning Moves, 2003 - designed by Christwart Conrad - translated by Pitt Crandlemire
'''Players''': For 2 - 4 players from 8 years
'''Game material''':
1 gameboard consisting of a 5x8 grid, 35 blockers, 8 gold mine markers showing the number of goldstrike points for that area, 4x16 chips with different numbers, 1 rules booklet
'''Idea of the game''':
Nuggets have been found in the Golden Valley! The gold diggers try to sell their claims to the big mining companies for as much as they can get by gathering as many Nuggets as possible. The players take on the role of prospectors and try through skillful placement of blockers to create valuable claims and then to control them with their high value chips. But the other players have not fallen on their heads and will compete for those claims quite lively, too If it all comes to naught, the claims are laid out once again. In the end, the one who walks away with the most money will be the one who bought up the most productive claims.
'''Set-up''':
The numbered stickers are stuck onto the gold mine markers and these are then placed on the board (see the illustration). Each player chooses a color and takes as many chips of that color in the appropriate value as indicated on the following table. He places these face-down in front of himself. In a 4-player game, players sitting opposite each other form a team.
'''Chip-distribution''':
2 players, each 16 11 2 1 1 1
3 players, each 11 7 2 1 1 -
4 players, each 8 5 1 1 1 -
The Gold mine markers are placed on the gameboard as follows:
(refer to illustration in German rules)
The youngest player begins the first game. In future games, the player that lost the most recent game always starts.
'''Course of the game'''
Play goes clockwise. On his turn, a player must execute one of the following actions: ''EITHER'' build two blockers ''OR'' place a chip on an unoccupied space
'''Build two blockers''':
In each case, the player places a blocker on any one unoccupied line between 2 spaces. The blockers need not be placed adjacent to each other. Restriction: a player may not place a blocker such that an area of less than 4 spaces is completely enclosed. Note: it is possible that there may be several gold mine markers in an area or even none at all.
'''Place a chip''':
The player places one of his colored chips face-down on any one unoccupied space (not already containing a chip or a gold mine marker). He secretly chooses which of his numbered chips he wishes to place. Players should decide at the beginning of the game whether players will be allowed to look at their own chips after they've been played or whether they'll simply be required to remember the numbers after they've been played..
'''Partnership game''':
Partners may communicate with each other in the 4-player game but they may not do so privately; the players on the other team must be able to see and hear everything. Also, partners may not show chips to each other.
'''End of the game''':
If a player has no more chips, he may still play blockers. Also, if there are no more blockers, a player may play his chips. Whenever a player can't or chooses not to play, he may pass but he may not then play again later. Once the last player has passed, the game ends.
'''Scoring''':
All chips are turned over. For each enclosed area, each player sums the points on his chips. The points of both partners are added together in the team game. The player with most points in an area gets all the gold mine markers in that area which score points equal to their value. Areas without gold mine markers score nothing. In the event of a tie in an area, the number of goldstrike points on the marker is divided among the tied players. (Half points are awarded when appropriate.) Whoever ultimately has acquired the most goldstrike points is able to mine the most gold Nuggets and wins the game.
0fd5e3724a47ed7d81f1689cd82c622ee19514e3
Contact us
0
9
993
139
2013-11-27T21:59:46Z
Sourisdudesert
1
wikitext
text/x-wiki
'''Board Game Arena''' is located in France.
== Contact e-mail ==
contact(at)boardgamearena.com
We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases:
* If you want to report a bug, please do it in the [http://boardgamearena.com/#!bugs bug reporting system]
* If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile.
== Postal address ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
980a98bd2ca063ac351422c896d84cf8920c62a0
996
993
2013-12-03T13:35:26Z
Januszk0
3262
wikitext
text/x-wiki
'''Board Game Arena''' znajduje się we Francji.
== Kontakt e-mail ==
contact(at)boardgamearena.com
Otrzymujemy '''wiele''' e-maili. Prosimy nie wysyłać do nas e-mail w każdym z tych dwóch przypadków:
* Jeśli chcesz zgłosić błąd, proszę zrobić to poprzez [http://boardgamearena.com/#!bugs System zgłaszania błędów]
* Jeśli chcesz zgłosić gracza naruszającego zasady BGA, użyj przycisku "Zgłoś tego gracza" na jego/jej profilu.
== Adres pocztowy ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
77f301b40cd095e78da87dc00bf3664ef39f8b38
Gamehelphex
0
139
1000
2013-12-07T04:58:53Z
Kennyyy
4327
Created page with "====GOAL==== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ====OPENING==== The first player..."
wikitext
text/x-wiki
====GOAL====
The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color).
====OPENING====
The first player places a first token on any cell of the board. The second player has then the choice between:
*continue playing his current color (and thus place a second token anywhere on the board);
*or decide to switch colors and keep the first move for him. In this case the first player plays another token with his new color.
====TURNS====
After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board.
====GAME ENDS====
The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie.
====VARIANTS====
The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays.
64c70a6a7b2646cee825432cab9587a99814c548
1001
1000
2013-12-07T04:59:35Z
Kennyyy
4327
wikitext
text/x-wiki
====GOAL====
The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color).
====OPENING====
The first player places a first token on any cell of the board. The second player has then the choice between:
*continue playing his current color (and thus place a second token anywhere on the board);
*or decide to switch colors and keep the first move for him. In this case the first player plays another token with his new color.
====TURNS====
After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board.
====GAME ENDS====
The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie.
====VARIANTS====
The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays.
38a20c50a816bc26f1dbc09c03711a1b96b2cb44
Gamehelphex
0
139
1002
1001
2013-12-07T05:00:27Z
Kennyyy
4327
wikitext
text/x-wiki
===GOAL===
The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color).
===OPENING===
The first player places a first token on any cell of the board. The second player has then the choice between:
*continue playing his current color (and thus place a second token anywhere on the board);
*or decide to switch colors and keep the first move for him. In this case the first player plays another token with his new color.
===TURNS===
After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board.
===GAME ENDS===
The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie.
===VARIANTS===
The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays.
0dbe66a3ee55bc0f448f3c6122e6f0e108827115
1003
1002
2013-12-07T05:21:26Z
Kennyyy
4327
wikitext
text/x-wiki
The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of this game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie.
===GOAL===
The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color).
===OPENING===
The first player places a first token on any cell of the board. The second player has then the choice between:
*continue playing his current color (and thus place a second token anywhere on the board);
*or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color.
===TURNS===
After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board.
===GAME ENDS===
The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie.
===VARIANTS===
The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays.
0c861842b852f6b5bcc5c19b2755d32b13bda7da
1006
1003
2013-12-07T05:23:50Z
Kennyyy
4327
wikitext
text/x-wiki
===INTRODUCTION===
The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of this game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie.
===GOAL===
The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color).
===OPENING===
The first player places a first token on any cell of the board. The second player has then the choice between:
*continue playing his current color (and thus place a second token anywhere on the board);
*or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color.
===TURNS===
After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board.
===GAME ENDS===
The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie.
===VARIANTS===
The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays.
21e638b436f93d68a93d5e59dbeea8b6778508a3
1007
1006
2013-12-07T05:26:21Z
Kennyyy
4327
wikitext
text/x-wiki
===INTRODUCTION===
The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of this game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie.
===GOAL===
The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color).
===OPENING===
The first player places a first token on any cell of the board. The second player has then the choice between:
*continue playing his current color (and thus place a second token anywhere on the board);
*or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color.
===TURNS===
After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board.
===GAME ENDS===
The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie.
===VARIANTS===
The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays.
67fcdd553674042e6c4fa1d29f0f0d75af0c10d8
1008
1007
2013-12-07T05:27:17Z
Kennyyy
4327
wikitext
text/x-wiki
===INTRODUCTION===
The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of the game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie.
===GOAL===
The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color).
===OPENING===
The first player places a first token on any cell of the board. The second player has then the choice between:
*continue playing his current color (and thus place a second token anywhere on the board);
*or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color.
===TURNS===
After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board.
===GAME ENDS===
The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie.
===VARIANTS===
The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays.
beddcbb667b6116e9af68afd6a17ecd86e092730
1014
1008
2013-12-09T14:15:39Z
Kennyyy
4327
wikitext
text/x-wiki
===INTRODUCTION===
Le jeu de Hex est un jeu de placement inventé indépendamment par deux mathématiciens, Piet Hein et John Nash, respectivement en 1942 et 1947. L’intérêt principal du jeu tiens a l'opposition entre la simplicité des règles et la complexité des stratégies mises en jeu. Qui plus est, le jeu ne peut finir en match nul, ce qui lui confère un autre aspect intéressant.
===OBJECTIF===
Pour chacun des joueurs le but du jeu est de créer une ligne de pions de sa couleur reliant ses deux cotes du plateau (de sa propre couleur également).
===OUVERTURE===
Le premier joueur joue un premier pion sur n'importe quelle case du plateau. Le second joueur a alors le choix entre:
*continuer a jouer avec sa couleur sur n'importe quelle autre case du plateau;
*ou décider d’échanger sa couleur avec son adversaire et de prendre le premier pion placé pour lui. Dans ce cas le premier joueur prend le prochain tour.
===TOURS===
Apres les deux premiers tours (voir OUVERTURE), chaque joueur joue un pion de sa couleur a son tour. Un pion peut-être placé sur n'importe quelle case libre du plateau.
===FIN===
Le jeu s’arrête lorsqu'un des joueur a créé une ligne continue antre ses deux cotes du plateau. Il ne peut y avoir d’égalité ou de jeu nul.
===VARIANTES===
Le jeu peut se jouer sur différentes tailles de plateau. Le 6x6 est a réserver aux débutant et permet d'apprendre facilement les règles et de repérer les premiers "motifs" de jeu. Le 11x11 est une taille classiquement jouée. Le 14x14 est la taille recommandée par John Nash, un des inventeur du jeu, tandis que le 15x15 permet des parties plus longues et potentiellement plus stratégiques.
6eb5ecead3656178d85c661827efabd26238db88
1016
1014
2013-12-11T07:05:32Z
Trociu
3428
wikitext
text/x-wiki
==Zasady gry==
Gra toczy się na planszy w kształcie rombu, złożonej z sześciokątnych pól. Rozmiar planszy może się zmieniać, ale liczba pól na każdym z boków jest zawsze stała. Tradycyjnie pojedynki rozgrywa się na planszy 11×11.
Każdy z dwóch graczy biorących udział w grze dysponuje kamieniami o odmiennych kolorach. Gracze na przemian układają kamienie na wolnych polach planszy, tak, aby sąsiadujące utworzyły nieprzerwany ciąg łączący boki planszy własnego koloru. Wygrywa ten z graczy, który ułoży taki ciąg jako pierwszy.
Często stosuje się dodatkową zasadę, mówiącą, że gracz wykonujący ruch jako drugi zamiast położyć swój kamień na wolnym polu może 'przejąć' kamień przeciwnika, tzn. zamienić jego kamień na swój. Dotyczy to tylko drugiego ruchu w rozgrywce (pierwszego ruchu drugiego gracza).
Ta zasada stosowana jest również tutaj.
b370555bab4642ec2ba6750e7dbe8afa6ab09e24
1017
1016
2013-12-11T10:51:12Z
Sourisdudesert
1
Reverted edits by [[Special:Contributions/Trociu|Trociu]] ([[User talk:Trociu|talk]]) to last revision by [[User:Kennyyy|Kennyyy]]
wikitext
text/x-wiki
===INTRODUCTION===
Le jeu de Hex est un jeu de placement inventé indépendamment par deux mathématiciens, Piet Hein et John Nash, respectivement en 1942 et 1947. L’intérêt principal du jeu tiens a l'opposition entre la simplicité des règles et la complexité des stratégies mises en jeu. Qui plus est, le jeu ne peut finir en match nul, ce qui lui confère un autre aspect intéressant.
===OBJECTIF===
Pour chacun des joueurs le but du jeu est de créer une ligne de pions de sa couleur reliant ses deux cotes du plateau (de sa propre couleur également).
===OUVERTURE===
Le premier joueur joue un premier pion sur n'importe quelle case du plateau. Le second joueur a alors le choix entre:
*continuer a jouer avec sa couleur sur n'importe quelle autre case du plateau;
*ou décider d’échanger sa couleur avec son adversaire et de prendre le premier pion placé pour lui. Dans ce cas le premier joueur prend le prochain tour.
===TOURS===
Apres les deux premiers tours (voir OUVERTURE), chaque joueur joue un pion de sa couleur a son tour. Un pion peut-être placé sur n'importe quelle case libre du plateau.
===FIN===
Le jeu s’arrête lorsqu'un des joueur a créé une ligne continue antre ses deux cotes du plateau. Il ne peut y avoir d’égalité ou de jeu nul.
===VARIANTES===
Le jeu peut se jouer sur différentes tailles de plateau. Le 6x6 est a réserver aux débutant et permet d'apprendre facilement les règles et de repérer les premiers "motifs" de jeu. Le 11x11 est une taille classiquement jouée. Le 14x14 est la taille recommandée par John Nash, un des inventeur du jeu, tandis que le 15x15 permet des parties plus longues et potentiellement plus stratégiques.
6eb5ecead3656178d85c661827efabd26238db88
1018
1017
2013-12-11T10:52:01Z
Sourisdudesert
1
wikitext
text/x-wiki
===INTRODUCTION===
The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of the game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie.
===GOAL===
The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color).
===OPENING===
The first player places a first token on any cell of the board. The second player has then the choice between:
*continue playing his current color (and thus place a second token anywhere on the board);
*or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color.
===TURNS===
After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board.
===GAME ENDS===
The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie.
===VARIANTS===
The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays.
beddcbb667b6116e9af68afd6a17ecd86e092730
Gamehelpquarto
0
140
1004
2013-12-07T05:21:34Z
Sooz
4387
Created page with "Quarto is a simple abstract game that should take about 15 mins. to play. '''To win, complete a row of 4 pieces (horizontally, vertically, or diagonally) that share at least ..."
wikitext
text/x-wiki
Quarto is a simple abstract game that should take about 15 mins. to play.
'''To win, complete a row of 4 pieces (horizontally, vertically, or diagonally) that share at least one trait in common'''. The twist to the game is that you select the piece your opponent places on the board and vice versa.
Pieces have 4 traits each which are a combination of the following:
- Tall or Short
- Dark or Light
- Round or Square
- Hollow or Solid
06255b5886333cb044a2c09873e72bf4d87658d4
1005
1004
2013-12-07T05:23:08Z
Sooz
4387
wikitext
text/x-wiki
Quarto is a simple abstract game that should take about 15 mins. to play.
'''To win, complete a row of 4 pieces (horizontally, vertically, or diagonally) that share at least one trait in common. The twist to the game is that you select the piece your opponent places on the board and vice versa.'''
Pieces have 4 traits each which are a combination of the following:
Tall or Short
Dark or Light
Round or Square
Hollow or Solid
f460fb16a46d83350325492ecd055c402e54c9a8
Game interface logic: yourgamename.js
0
88
1009
988
2013-12-08T02:50:31Z
Kennyyy
4327
Specification about image preloading: don't need to specify for image boxes
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ).play();
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
'''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
bcb948111c1d9401116fc8dcab816d616cd5b6d4
Gamehelpthejellymonsterlab
0
141
1010
2013-12-09T13:06:02Z
Adela82
4198
Created page with "In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you nee..."
wikitext
text/x-wiki
In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters.
At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand.
Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours.
While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand.
In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five).
When a player has 5 monsters done, the center is open to close the game. Any player who goes there, finishes the game.
Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner.
The player with the most score points win the game.
Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit.
ea8f82efbfe9ed3393312c857edc04e17a832170
1011
1010
2013-12-09T13:06:11Z
Adela82
4198
wikitext
text/x-wiki
In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters.
At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand.
Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours.
While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand.
In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five).
When a player has 5 monsters done, the center is open to close the game. Any player who goes there, finishes the game.
Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner.
The player with the most score points win the game.
Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit.
e3493b9fd52feb5d855a879718adb71b39011ae6
1012
1011
2013-12-09T13:12:21Z
Adela82
4198
wikitext
text/x-wiki
In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters.
At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand.
Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours.
While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand.
In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five).
When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game.
Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner.
The player with the most score points win the game.
Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit.
f1283bc465bc59648625e6db6744eadef7312970
1013
1012
2013-12-09T13:13:29Z
Adela82
4198
wikitext
text/x-wiki
In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters.
At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand.
Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours.
While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand.
In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five).
When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game.
Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner of the playboard.
The player with the most score points win the game.
Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit.
1665b014e042e0a25ddc91de3c09a9b522506855
1019
1013
2013-12-11T22:18:42Z
Trociu
3428
wikitext
text/x-wiki
==Cel gry==
Zdobyć jak najwięcej punktów za stworzone potwory
==Tworzenie potwora==
Każdy potwór składa się z:
- oczu: może mieć jedno, dwoje lub troje oczu
- buzi: może mieć uśmiech albo grymas
- ciała: może być czerwone, zielone, różowe bądź niebieskie
Każdy potwór tworzony jest też w jednym, konkretnym laboratorium (z 6 dostępnych).
Każda część potwora występują w określenie ilości i widać to na ściądze.
Liczba punktów to cyfra w gwiazdce - zarazem oznacza jak trudno jest takiego potwora złożyć (tzn. na im mniej pospolitych fragmentach bazuje).
==Zasady gry==
Gracze na zmiany wykonują swoje tury. W czasie swojej tury gracz musi przemieścić się do sąsiedniego laboratorium (z wyjątkiem tych w których już był - określa to żeton w kolorze gracza) lub do środkowej talii talii.
Środkowa talia to talia eksperymentów, więc wejście tam wiąże się zawsze z pociągnięciem dodatkowej karty eksperymentu. Jeżeli gracz ma już 5 kart na ręce to nie może tam wejsc (jest to limit kart na ręce). Jeżeli nie może też pójść do innego laboratorium zmuszony jest pozostawić jedną kartę w laboratorium, w którym się znajduje i tym samym traci kolejkę.
Gracz, który wchodzi do laboratorium może między nim a swoją ręką przenosić dowolną ilość kart pamiętając o limicie kart na ręce (5 kart). Mogą to być zarówno karty eksperymentów jak i części potwora.
Aby stworzyć potwora gracz musi w odpowiednim laboratorium zostawić zarówno części potwora jak i kartę eksperymentu. Potwór jest stworzony dopiero w momencie kiedy inny gracz odwiedzi to laboratorium (po to m.in są znaczniki śladu - by zaznaczyć kto był ostatnio i być może stworzył potwora). Po stworzeniu potwora kartę eksperymentu przekazuje się twórcy (osobie, która ją tam umieściła) i stanowi ona jego punkty. CZĘŚCI POTWORA ZOSTAJĄ W LABORATORIUM I MOŻNA JE WYKORZYSTAĆ NAWET W TEJ SAMEJ TURZE DO STWORZENIA POTWORA!
==Koniec gry==
Jeżeli ktoś stworzy 4 potwory (lub więcej - zależne od ustawień stołu) to od tego momentu gra się kończy po turze gracza, który wszedł na środkowy stos. Punkty to cyfry w gwiazdkach i na ich podstawie określa się zwycięzcę.
fb8575a9882d5d5fac24591bc1c4a5659306159c
1020
1019
2013-12-12T19:25:32Z
Trociu
3428
wikitext
text/x-wiki
In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters.
At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand.
Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours.
While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand.
In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five).
When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game.
Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner of the playboard.
The player with the most score points win the game.
Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit.
1665b014e042e0a25ddc91de3c09a9b522506855
Gamehelpraceforthegalaxy
0
41
1015
843
2013-12-11T06:01:20Z
Sooz
4387
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
38dad590c7c548f8bc06cb4fe31ff392cc69d862
1029
1015
2014-01-06T07:51:31Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
b9a76b03a12de68b52a18216d1315508178cd908
1030
1029
2014-01-06T07:52:19Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
82a71cf988b934c0e3883288700b4fae9c846cb1
1031
1030
2014-01-06T07:52:29Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
70967f57bb4d0ff1597fccbd5e6877e460d9bb48
1032
1031
2014-01-06T08:01:38Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
1f7c743a1f6a43edfe085a83425cb51510c5e563
1033
1032
2014-01-06T08:17:40Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
5bdb5660524e4b8f45c515073c8005e7172effdd
1034
1033
2014-01-06T08:17:56Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from /nyour hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
733712790d9a029ae02283aa7855f2904fc26c0d
1035
1034
2014-01-06T08:18:21Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
5bdb5660524e4b8f45c515073c8005e7172effdd
1036
1035
2014-01-06T08:39:16Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech
Green = Genes
Brown = Rare Elements
Blue = Novelty Goods
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from
your hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
1f2c804430fd2d2c4d65bc03523df7b5c9742cac
1037
1036
2014-01-06T08:39:50Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech (5)
Green = Genes (4)
Brown = Rare Elements (3)
Blue = Novelty Goods (2)
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a card from
your hand to draw new cards (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
acb372225d62f3f811ece974356cadefdbcf1dc3
1038
1037
2014-01-06T08:40:34Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech (5)
Green = Genes (4)
Brown = Rare Elements (3)
Blue = Novelty Goods (2)
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a resource
from your hand to draw cards equal to its trade value (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
ca32e154d43da007610ffa53f4b079f5154805e4
1039
1038
2014-01-06T08:42:03Z
Drchinchilla
4623
wikitext
text/x-wiki
In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments.
The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments.
There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins.
The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner!
In case of a tie, the player with the most goods on the board plus cards in hand wins.
You may drag a resource (single-coloured small card) to a consumption power to consume it.
'''Summary of Goods'''
Yellow = Alien Tech (trade value = 5)
Green = Genes (4)
Brown = Rare Elements (3)
Blue = Novelty Goods (2)
'''Summary of Phases'''
Explore = draw 2 cards; keep 1, discard the other
Develop = place and pay for a development
Settle = place and pay for a world, receiving any windfall as indicated
Consume = use consume powers if possible, typically to discard goods for victory point chips
Produce = place a good on each world without a good that produces one
'''Phase Bonuses'''
These are the bonuses you gain for choosing each phase:
Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card
Develop = discard 1 less card when paying for the development
Settle = draw 1 card after settling a world
Consume = Gain double victory points for consumed goods OR trade by discarding a resource
from your hand to draw cards equal to its trade value (bonuses from $ row apply)
Produce = Produce a good on one windfall world that does not already have a good
d7a783556bd5db9c8aebfe061b5b77ac0f4570b0
Contact us
0
9
1021
996
2013-12-18T21:14:23Z
Een
3
Reverted edits by [[Special:Contributions/Januszk0|Januszk0]] ([[User talk:Januszk0|talk]]) to last revision by [[User:Sourisdudesert|Sourisdudesert]]
wikitext
text/x-wiki
'''Board Game Arena''' is located in France.
== Contact e-mail ==
contact(at)boardgamearena.com
We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases:
* If you want to report a bug, please do it in the [http://boardgamearena.com/#!bugs bug reporting system]
* If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile.
== Postal address ==
G. Isabelli
19 bd république
92 260 Fontenay-aux-Roses
FRANCE
+33 6 17 25 80 34
980a98bd2ca063ac351422c896d84cf8920c62a0
Gamehelptakenoko
0
104
1022
697
2013-12-22T11:40:22Z
Samc1078
4475
Re-wording of the Wind Action.
wikitext
text/x-wiki
Quick Reference Guide
Each turn consists of 2 steps:
1) Determine weather
2) Perform 2 different actions and complete objectives
Weather Types (always optional)
Sun - take a 3rd action
Rain - grow 1 bamboo on any irrigated plot
Wind - "may" take two identical actions this turn
Storm - move panda to any plot and he eats a bamboo as normal
Clouds - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather for this turn
Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed.
Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo.
Plots can only be placed adjacent to the pond or where it is next to 2 other plots in play.
The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color.
Game ends when a certain number of objectives have been completed.
2 players - 9 objectives
3 players - 8 objectives
4 players - 7 objectives
The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn.
The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win.
2cd92079359df73e8679ce2711f60b62d4f58bfe
Gamehelpacquire
0
142
1023
2013-12-23T19:08:08Z
Scooby rex
4486
Created page with "The main object of Acquire is to become the wealthiest player by the end of the game. This is done by forming hotel chains, shrewdly buying the right stock at the right time,..."
wikitext
text/x-wiki
The main object of Acquire is to become the wealthiest player by the end of the game. This is done by forming hotel chains, shrewdly buying the right stock at the right time, merging chains to obtain capital and adding hotels to the chains in which you have controlling interest to increase their value.
At the beginning of the game, each player receives $6,000. To determine who plays first, each player draws one tile (representing a hotel) and places it in its matching square on the board. (No chains are formed at this time.) The player who has drawn the lowest number-letter combination starts play. Each player draws six hotels from the central cluster of face-down tiles on the table and keeps them in his/her "hand", not allowing other players to see them.
Each player’s turn consists of:
1. Placing one of his hotel tiles on its matching square on the board. If this hotel creates a chain or causes a merger, all transactions connected with Creating Chains or Merging Chains are completed before the player’s turn continues.
2. Buying Stock. If, after placing his hotel, there are one or more hotel chains on the board, the player may, if he wishes, buy stock in one or more of them. (See Buying Stock).
3. Drawing another hotel tile to replace the one played.
CREATING NEW CHAINS
When a player places a hotel tile next to one already on the board (rank or file—not diagonally), a chain is created. For example, hotel tiles A1 and B2 are on the board but do not form a chain as they adjoin diagonally (not rank or file). Assume that among his six hotels, a player has C2 and B1. He places C2, creating a two-hotel chain. (If he had placed B1, he would have created a three-hotel chain; see above diagram.) Then assume that, on his next turn, he places B1, expanding the chain to four hotels.
The maker of a chain chooses its name from seven possible chains, taking the appropriate chain marker and placing it atop any one hotel in the chain. He then receives a "Founder’s Bonus" of one free stock in that chain. A maximum of seven chains may be on the board at one time. Any hotel which would create an eighth chain may not be placed.
MERGING CHAINS
When a player places a hotel adjacent to two (or more) chains, a merger takes place. The chain with more member hotels takes over the other(s). If the chains are the same size before the merging hotel was placed, the person who made the merger chooses which chain takes over. The chain marker of the now defunct chain is removed. (See below, at Multiple Mergers, for what to do when placing one hotel that merges more than one chain).
A chain containing 11 or more hotels is "safe" and cannot be taken over by another chain. A player may not place a hotel which would merge two safe chains. A safe chain may still take over an open chain, however.
MAJORITY HOLDER'S BONUS. At merger time, bonuses are paid to the two largest shareholders in the defunct chain. In the case of a tie for the title of largest shareholder, the first and second bonuses are combined and divided equally between the tying shareholders. In the case of a tie for the title of second largest shareholder, the second bonus is divided equally between the tying players. If only one player holds stock in the defunct chain, he receives both bonuses.
DISPOSAL OF STOCK AT TIME OF MERGER. After the bonuses have been paid, each player, starting with the merger maker and continuing clockwise, handles his/her stock in the defunct chain in one or more of the following ways:
1. Hold: Stock may be held in expectation of starting another chain with that name.
2. Sell: Stock may be sold to Stock Market at a price determined by the number of hotels in the defunct chain before the merger.
3. Trade: Stock may be traded at the rate of two blocks of defunct stock for one block of controlling chain stock. (If the Stock Market has no remaining blocks of controlling chain stock, players may not trade).
MULTIPLE MERGERS. When multiple mergers (mergers of more than two chains at once) occur, the larger chain takes over all smaller chains simultaneously. The multiple merger is then handled as individual mergers. Majority holder’s bonuses are paid for the larger of defunct chains and players dispose of their stock in this chain. Then the smaller defunct chain is handled in the same manner. In the case of a tie, the merger maker chooses which defunct chain is to be handled first. Bonuses and stock prices are determined by the number of hotels in the defunct chain before the merger.
BUYING STOCK
Any player, immediately after playing his hotel, may buy stock in any active chain—up to a maximum of three blocks in any one turn. If he is unable to place any of his hotels, he may still buy stock. His purchase may be in one, two or three different chains. Price per block varies with the number of hotels in the chain.
A player who runs out of money cannot buy stock but must place a hotel if he is able. He cannot raise money by selling stock except during the designated disposal period after a merger. Trading and selling of stock between players is not permitted. At any time, player may ask how much stock remains in a particular chain.
ENDING THE GAME
The game ends when one player, during his turn, announces that either all chains on board are "safe" or that any one chain contains 41 or more hotels. A player does not have to announce that the game is over if it is to his advantage to continue playing. After announcing that the game is over, the player may still complete his turn.
To determine the winner, all chains are bought out by the bank. Majority holder’s bonuses are paid for all active chains. All players sell their stock. Stock in a chain that is not on the board is worthless. The player with the most money is the winner.
6daccd417644006bb74530f1659ad57b06feb515
Gamehelpsaboteur
0
32
1024
85
2014-01-03T13:59:28Z
Tomcio8802
4596
/* Available variants */
wikitext
text/x-wiki
== Goal ==
Get as many gold nuggets as possible during the three rounds of the game.
In order to do so,
# if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards
# if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers from getting to the treasure.
Your role (gold digger or saboteur) will be randomly selected at the start of each round.
== Rules summary ==
On your turn, you must click on a card from your hand to select it, then play this card or discard it.
You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card.
The cards are of several types:
* 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card.
* 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score).
* 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you.
* 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about.
* 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove.
== Cards in play ==
* 44 'Path' cards
* 9 'Sabotage' cards (three for each tool)
* 6 'Repair a tool' cards (two for each tool)
* 3 'Repair a tool among these two' cards (one for each combination of two tools)
* 5 'Map' cards (one less than in the box set, as requested by the game author)
* 3 'Rock fall' cards
* 28 'Gold' cards
** 16 with one gold nugget
** 8 with two gold nuggets
** 4 with three gold nuggets
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
The Official Anthem of Saboteur designed by '''Dzikidon'''
Music - '''Adele - Skyfall''':
*This is the end
*Hold your breath and count to ten
*Feel the Earth move and then
*Hear your axe burst again
*For this is the end
*I’ve digged and dreamt this moment
*I will repair I owe them
*Even tho' I’m broken
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*At rock fall
*At rock fall
*Rock fall is where we start
*A thousand miles and cards apart
*Where roads collide and caves are dark
*You may fix my trolley
*You can break my lamp
*But you’ll never have my gold
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*(Let the rock fall)
*When it crumbles
*We will stand tall) / x2
*Where you go I go
*What you see I see
*I know I'd never be me
*Without the security
*Of your fixing cards
*Keeping me from harm
*Put your end in their straight
*And we'll stand
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*Let the rock fall
*We will stand tall
*At rock faaall
a26d5ddfd4f3a8f6cb5a00a894689eba87be1aeb
1025
1024
2014-01-03T15:40:21Z
Dzikidon
4598
wikitext
text/x-wiki
== Goal ==
Get as many gold nuggets as possible during the three rounds of the game.
In order to do so,
# if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards
# if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers from getting to the treasure.
Your role (gold digger or saboteur) will be randomly selected at the start of each round.
== Rules summary ==
On your turn, you must click on a card from your hand to select it, then play this card or discard it.
You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card.
The cards are of several types:
* 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card.
* 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score).
* 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you.
* 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about.
* 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove.
== Cards in play ==
* 44 'Path' cards
* 9 'Sabotage' cards (three for each tool)
* 6 'Repair a tool' cards (two for each tool)
* 3 'Repair a tool among these two' cards (one for each combination of two tools)
* 5 'Map' cards (one less than in the box set, as requested by the game author)
* 3 'Rock fall' cards
* 28 'Gold' cards
** 16 with one gold nugget
** 8 with two gold nuggets
** 4 with three gold nuggets
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
The Official Anthem of Saboteur designed by '''Dzikidon''' and '''Sikora8a'''
Music - '''Adele - Skyfall''':
*This is the end
*Hold your breath and count to ten
*Feel the Earth move and then
*Hear your axe burst again
*For this is the end
*I’ve digged and dreamt this moment
*I will repair I owe them
*Even tho' I’m broken
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*At rock fall
*At rock fall
*Rock fall is where we start
*A thousand miles and cards apart
*Where roads collide and caves are dark
*You may fix my trolley
*You can break my lamp
*But you’ll never have my gold
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*(Let the rock fall)
*When it crumbles
*We will stand tall) / x2
*Where you go I go
*What you see I see
*I know I'd never be me
*Without the security
*Of your fixing cards
*Keeping me from harm
*Put your end in their straight
*And we'll stand
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*Let the rock fall
*We will stand tall
*At rock faaall
30b04f63dd36cb299d123cf23b3b25817fc5692a
Faq
0
3
1026
968
2014-01-04T14:21:38Z
Scooby rex
4486
/* What is forbidden on Board Game Arena? */
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple account and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
ea83ef3f991f3e664f77c8065e4eb3e9fc45eaf1
1027
1026
2014-01-04T14:22:20Z
Scooby rex
4486
/* What is absolutely forbidden in Board Game Arena? */
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple accounts and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had a bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
642a6f93e07228e0a55c19a3084a2d07d8f425f3
1028
1027
2014-01-04T14:23:36Z
Scooby rex
4486
/* What if some player does something wrong? */
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple accounts and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
6d2f68407a8ecc16b22184f0a4513f30c364e426
Main game logic: yourgamename.game.php
0
86
1040
946
2014-01-06T08:45:43Z
Sourisdudesert
1
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this:
<pre>
'tie_breaker_description' => totranslate("Describe here your tie breaker formula"),
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaVisibleSystemException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
== Player elimination ==
In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end.
This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature is
e8c03a720c7bf9dd99f27da4b138df14a86868a0
1041
1040
2014-01-06T08:53:15Z
Sourisdudesert
1
/* Player elimination */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states.
* Game state actions: the logic to run when entering a new game state.
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this:
<pre>
'tie_breaker_description' => totranslate("Describe here your tie breaker formula"),
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaVisibleSystemException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
== Player elimination ==
In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end.
This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow").
Usage:
* Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state).
* In your PHP code:
self::eliminatePlayer( <player_to_eliminate_id> );
* the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now.
* When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results.
62154d567a823d8cb941350f88708e148cd49684
1042
1041
2014-01-06T09:00:34Z
Sourisdudesert
1
/* File Structure */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]).
* Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]).
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this:
<pre>
'tie_breaker_description' => totranslate("Describe here your tie breaker formula"),
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaVisibleSystemException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
== Player elimination ==
In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end.
This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow").
Usage:
* Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state).
* In your PHP code:
self::eliminatePlayer( <player_to_eliminate_id> );
* the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now.
* When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results.
145ce8691534997b3b513ef02519689d6e065ee9
Your game state machine: states.inc.php
0
90
1043
804
2014-01-06T09:09:19Z
Sourisdudesert
1
/* args */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"args" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn", <================================== HERE
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
</pre>
It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php):
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves()
);
}
</pre>
Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn :
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above).
Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn).
==== Private infos in args ====
By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic.
This is although possible to specify that some data should be sent to some specific players only:
Example 1: send an information to active player(s) only:
<pre>
function argPlayerTurn()
{
return array(
'_private' => array( // Using "_private" keyword, all data inside this array will be made private
'active' => array( // Using "active" keyword inside "_private", you select active player(s)
'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s)
)
),
'possibleMoves' => self::getPossibleMoves() // will be send to all players
);
}
</pre>
Example 2: send an information to a specific player (<specific_player_id>) only:
<pre>
function argPlayerTurn()
{
return array(
'_private' => array( // Using "_private" keyword, all data inside this array will be made private
<specific_player_id> => array( // you select one specific player with its id
'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id>
)
),
'possibleMoves' => self::getPossibleMoves() // will be send to all players
);
}
</pre>
IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed.
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
662e0aefe4d493cd3263698181e113351d75c6a2
Moderationpolicy
0
123
1044
867
2014-01-06T12:17:50Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
* the player has been reported several times for the same type of case.
* the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
* on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games played.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: explicit sexual content, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (explicit sexual content, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one noticed the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it has to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong intent to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. It is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP address, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Translation stealing / vandalism
| The player is writing inappropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their allotted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
fd3b875814a1865e5ca8f4def483c31d94b46a3b
1045
1044
2014-01-06T12:23:54Z
Sourisdudesert
1
/* Penalty grid */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
* the player has been reported several times for the same type of case.
* the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
* on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games played.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: explicit sexual content, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (explicit sexual content, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one noticed the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it has to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong intent to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. It is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP address, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Spam / advertising / inappropriate links
| The player is using BGA for advertising. In particular: links not related to the purpose of the page, advertising for other online boardgaming websites, spam, ...
|
|-
! Something else
| Translation stealing / vandalism
| The player is writing inappropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their allotted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
34ec666062af04c36bf1fccc6cc61e8f415eb55b
1046
1045
2014-01-06T13:24:42Z
Sourisdudesert
1
/* About private jokes */
wikitext
text/x-wiki
== General rules ==
=== Beyond a Reasonable Doubt ===
In case there is a any possible doubt, a player should be considered not guilty.
=== Moderators independance ===
Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly.
=== Appeal ===
Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com".
They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties.
=== Penalty grid ===
Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties:
* the player has been reported several times for the same type of case.
* the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people.
* on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice.
=== Relapse ===
In case there is a relapse, the penalty increases exponentially.
This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty.
Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent.
Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses.
=== Special urgency ban procedure ===
Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...).
=== About private jokes ===
If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report.
Note: in case a moderator discovers that this is obviously not a private joke and that something must be reported, the moderator is allowed to create a report for the case. However, in this case, this moderator is not allowed to judge the report.
=== Prescription ===
For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old.
=== Player profile influence ===
The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other.
The player profile is NOT taken into account when choosing the penalty if the player is found guilty.
Good profile elements are:
* A good thumb up / thumb down ratio.
* Player is registered since a long time / has a lot of games played.
* Players is involved in the website (ex: realized translations).
* Player is supporting BGA (member of the club).
=== Incomplete reports ===
Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report.
== Penalty grid ==
{| class="wikitable alternance centre"
|+ Titre
|-
! scope="col" | Category
! scope="col" | Case type
! scope="col" | Details
! scope="col" | Standard penalty
|-
! Insults
| Insults during a game, on table chat
| Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on general chat
| Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban.
|-
! Insults
| Insults on public space (wall, forum, comments...)
| Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Aggressive attitude
| Aggressive attitude during a game: can't wait the other player, provocation, ...
| As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed.
| -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed.
|-
! Avatar
| Inappropriate avatar: explicit sexual content, extreme violence, advertising...
| If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases:
1°) It can hurt underage players (explicit sexual content, extreme violence)
2°) This is advertisement / this violate some intellectual property
3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross)
| Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced.
|-
! Avatar
| Inappropriate username
| If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA.
| Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one noticed the username until now, it is probably not inappropriate.
|-
! Table description
| Inappropriate table description
| If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people.
| Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban.
|-
! Kingmaking
| Kingmaking action during a game
| The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it has to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Bug exploit
| Exploit a known bug during a game
| The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned.
| No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done.
|-
! Private information
| Some player gives some private information during the game
| Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong intent to kill the pleasure of the game by giving some private information during the game.
| -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties.
|-
! Multiple accounts
| A player is using multiple accounts (most of the time: to boost his ELO rank)
| The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. It is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP address, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way.
| For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games.
|-
! Something else
| Spam / advertising / inappropriate links
| The player is using BGA for advertising. In particular: links not related to the purpose of the page, advertising for other online boardgaming websites, spam, ...
|
|-
! Something else
| Translation stealing / vandalism
| The player is writing inappropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership,
| Immediate ban from the website (to avoid vandalism).
|-
! Something else
| Player is slow to play
| Players have the right to think as long as they do not go over their allotted time. If the player is slow on purpose, the good answer is: thumb down.
| No penalty
|-
! Something else
| Player quit the game before the end
| In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else.
| No penalty
|-
|}
91f7c78eaee74c38df5fac94a13f00cfe84fbd06
Tutorial reversi
0
57
1047
937
2014-01-09T23:31:57Z
Deluxe flame
4630
/* Make the squares appears */
wikitext
text/x-wiki
== Introduction ==
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.
Before you read this tutorial, you must:
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript.
== Create your first game ==
With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games.
Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah.
== Let it look like Reversi ==
It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later.
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).
For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528):
[[File:Board.jpg]]
Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose.
Now, let's make it appears on our game:
* upload board.jpg in your "img/" directory.
* edit "reversi_reversi.tpl" to add a 'div' for your board:
<pre>
<div id="board">
</div>
</pre>
* edit your reversi.css file to transform it into a visible board:
#board {
width: 536px;
height: 528px;
background-image: url('img/board.jpg');
}
Refresh your page. Here's your board:
[[File:reversi1.jpg]]
== Make the squares appears ==
Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs.
Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature.
Let's modify our template like this:
<pre>
<div id="board">
<!-- BEGIN square -->
<div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div>
<!-- END square -->
</div>
</pre>
As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load.
Let's do it in our "reversi.view.php" file:
<pre>
$this->page->begin_block( "reversi_reversi", "square" );
$hor_scale = 64.8;
$ver_scale = 64.4;
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$this->page->insert_block( "square", array(
'X' => $x,
'Y' => $y,
'LEFT' => round( ($x-1)*$hor_scale+10 ),
'TOP' => round( ($y-1)*$ver_scale+7 )
) );
}
}
</pre>
Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here.
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:
<pre>
#board {
width: 536px;
height: 528px;
background-image: url('img/board.jpg');
position: relative;
}
.square {
width: 62px;
height: 62px;
position: absolute;
background-color: red;
}
</pre>
Explanations:
* With "position: relative" on board, we ensure square elements are positioned relatively to board.
* For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements.
Let's refresh and check our our (beautiful) squares:
[[File:reversi2.jpg]]
== The discs ==
Now, our board is ready to receive some disc tokens!
At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template):
<pre>
<!-- END square -->
<div id="tokens">
</div>
</div>
</pre>
Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file:
[[File:tokens.png]]
Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].
Now, let's separate the disc with some CSS stuff:
<pre>
.token {
width: 56px;
height: 56px;
position: absolute;
background-image: url('img/tokens.png');
}
.tokencolor_ffffff { background-position: 0px 0px; }
.tokencolor_000000 { background-position: -56px 0px; }
</pre>
With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah.
Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions.
Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template".
In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token:
<pre>
<script type="text/javascript">
// Templates
var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>';
</script>
</pre>
Note: we already created the "templates" section for you in the game skeleton.
As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets).
Now, let's create a method in our Javascript code that will make a token appear on the board, using this template:
<pre>
addTokenOnBoard: function( x, y, player )
{
dojo.place( this.format_block( 'jstpl_token', {
x_y: x+'_'+y,
color: this.gamedatas.players[ player ].color
} ) , 'tokens' );
this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player );
this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play();
},
</pre>
At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element.
Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination.
Note: don't forget to call the "play()", otherwise the token remains at its original location.
Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree.
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:
<pre>
$default_colors = array( "ffffff", "000000" );
</pre>
Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this:
[[File:reversi3.jpg]]
== The database ==
We did most of the client-side programming, so let's have a look on the other side now.
To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance.
Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file.
[[File:reversi4.jpg]]
The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this:
<pre>
CREATE TABLE IF NOT EXISTS `board` (
`board_x` smallint(5) unsigned NOT NULL,
`board_y` smallint(5) unsigned NOT NULL,
`board_player` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`board_x`,`board_y`)
) ENGINE=InnoDB;
</pre>
Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game.
== Setup the initial game position ==
The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board).
Let's do this:
<pre>
// Init the board
$sql = "INSERT INTO board (board_x,board_y,board_player) VALUES ";
$sql_values = array();
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );
for( $x=1; $x<=8; $x++ )
{
for( $y=1; $y<=8; $y++ )
{
$token_value = "NULL";
if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player
$token_value = "'$whiteplayer_id'";
else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player
$token_value = "'$blackplayer_id'";
$sql_values[] = "('$x','$y',$token_value)";
}
}
$sql .= implode( $sql_values, ',' );
self::DbQuery( $sql );
// Active first player
self::activeNextPlayer();
</pre>
As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token.
At the end, we call activeNextPlayer to make the first player active at the beginning of the game.
Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload):
<pre>
// Get reversi board token
$result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player
FROM board
WHERE board_player IS NOT NULL" );
</pre>
As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes.
The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method:
<pre>
for( var i in gamedatas.board )
{
var square = gamedatas.board[i];
if( square.player !== null )
{
this.addTokenOnBoard( square.x, square.y, square.player );
}
}
</pre>
As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method.
Reload... and here we are:
[[File:reversi5.jpg]]
It starts to smell Reversi here...
== The game state machine ==
Now, let's stop our game again, because we are going to start the core game logic.
You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine:
[[File:reversi6.jpg]]
And here's our "states.inc.php", according to this diagram:
<pre>
$machinestates = array(
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 10 )
),
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn",
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
11 => array(
"name" => "nextPlayer",
"type" => "game",
"action" => "stNextPlayer",
"updateGameProgression" => true,
"transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 )
),
99 => array(
"name" => "gameEnd",
"description" => clienttranslate("End of game"),
"type" => "manager",
"action" => "stGameEnd",
"args" => "argGameEnd"
)
);
</pre>
Now, let's create in reversi.game.php the methods that are declared in this game states description file:
* argPlayerTurn
* stNextPlayer
... and start a new Reversi game.
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"):
[[File:reversi7.jpg]]
== The rules ==
Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular:
* As we just said, to help the player to see where he can play.
* When the player play, to check if he has the right to play here.
This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is:
* Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y.
* Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move.
One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods.
If you want to look into details, please look at the "utility method" sections of reversi.game.php.
== Display allowed moves ==
Now, what we want to do is highlight squares where player can place a disc.
To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side:
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() )
);
}
</pre>
We are of course using the "getPossibleMoves" method we just developed.
Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this:
<pre>
updatePossibleMoves: function( possibleMoves )
{
// Remove current possible moves
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
for( var x in possibleMoves )
{
for( var y in possibleMoves[ x ] )
{
// x,y is a possible move
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
}
}
this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') );
},
</pre>
The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it:
<pre>
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
</pre>
At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method.
Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square.
Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning.
And here we are:
[[File:reversi8.jpg.jpg]]
== Let's play ==
From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:
* When we click on a "possibleMove" square, send the move to the server.
* Server side, check the move is correct, apply Reversi rules and jump to next player.
* Client side, change the disc position to reflect the move.
Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method:
<pre>
dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' );
</pre>
Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square.
Here's our "onPlayDisc" method below:
<pre>
onPlayDisc: function( evt )
{
// Stop this event propagation
dojo.stopEvent( evt );
// Get the cliqued square x and y
// Note: square id format is "square_X_Y"
var coords = evt.currentTarget.id.split('_');
var x = coords[1];
var y = coords[2];
if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{
// This is not a possible move => the click does nothing
return ;
}
if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment
{
this.ajaxcall( "/reversi/reversi/playDisc.html", {
x:x,
y:y
}, this, function( result ) {} );
}
},
</pre>
What we do here is:
* We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea.
* We get the x/y coordinates of the square by using "evt.currentTarget.id".
* We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there.
* We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square.
* Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y.
Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php":
<pre>
public function playDisc()
{
self::setAjaxMode();
$x = self::getArg( "x", AT_posint, true );
$y = self::getArg( "y", AT_posint, true );
$result = $this->game->playDisc( $x, $y );
self::ajaxResponse( );
}
</pre>
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic.
Now, let's have a look of this playDisc method:
<pre>
function playDisc( $x, $y )
{
// Check that this player is active and that this action is possible at this moment
self::checkAction( 'playDisc' );
</pre>
... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat).
<pre>
// Now, check if this is a possible move
$board = self::getBoard();
$player_id = self::getActivePlayerId();
$turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board );
if( count( $turnedOverDiscs ) > 0 )
{
// This move is possible!
</pre>
...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible.
<pre>
// Let's place a disc at x,y and return all "$returned" discs to the active player
$sql = "UPDATE board SET board_player='$player_id'
WHERE ( board_x, board_y) IN ( ";
foreach( $turnedOverDiscs as $turnedOver )
{
$sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),";
}
$sql .= "('$x','$y') ) ";
self::DbQuery( $sql );
</pre>
... we update the database to change the color of all turned over disc + the disc we just placed.
<pre>
// Update scores according to the number of disc on board
$sql = "UPDATE player
SET player_score = (
SELECT COUNT( board_x ) FROM board WHERE board_player=player_id
)";
self::DbQuery( $sql );
// Statistics
self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id );
if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) )
self::incStat( 1, 'discPlayedOnCorner', $player_id );
else if( $x==1 || $x==8 || $y==1 || $y==8 )
self::incStat( 1, 'discPlayedOnBorder', $player_id );
else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 )
self::incStat( 1, 'discPlayedOnCenter', $player_id );
</pre>
... now, we update both player score by counting all disc, and we manage game statistics.
<pre>
// Notify
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
self::notifyAllPlayers( "turnOverDiscs", '', array(
'player_id' => $player_id,
'turnedOver' => $turnedOverDiscs
) );
$newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true );
self::notifyAllPlayers( "newScores", "", array(
"scores" => $newScores
) );
</pre>
... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log.
<pre>
// Then, go to the next state
$this->gamestate->nextState( 'playDisc' );
}
else
throw new feException( "Impossible move" );
}
</pre>
... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above).
To make the statistics work, we have to initialize them in state.inc.php:
<pre>
// Statistics existing for each player
"player" => array(
"discPlayedOnCorner" => array( "id"=> 10,
"name" => totranslate("Discs played on a corner"),
"type" => "int" ),
"discPlayedOnBorder" => array( "id"=> 11,
"name" => totranslate("Discs played on a border"),
"type" => "int" ),
"discPlayedOnCenter" => array( "id"=> 12,
"name" => totranslate("Discs played on board center part"),
"type" => "int" ),
"turnedOver" => array( "id"=> 13,
"name" => totranslate("Number of discs turned over"),
"type" => "int" )
)
</pre>
A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state:
<pre>
function stNextPlayer()
{
// Activate next player
$player_id = self::activeNextPlayer();
self::giveExtraTime( $player_id );
$this->gamestate->nextState( 'nextTurn' );
}
</pre>
Now, when we play a disc, the rules are checked and the disc appears in the database.
[[File:reversi9.jpg]]
Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board.
== Make the move appear automatically ==
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.
In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'):
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 );
dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" );
this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 );
</pre>
As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:
* Make a disc slide from the player panel to its place on the board
* (wait 500ms)
* Make all turned over discs blink (and of course turned them over)
* (wait 1500ms)
* Let the next player play.
Let's have a look now on the "playDisc" notification handler method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
No surprise here, we re-used some existing stuff to:
* Remove the highlighted squares.
* Add a new disc on board, coming from player panel.
Now, here's the method that handles the turnOverDiscs notification:
<pre>
notif_turnOverDiscs: function( notif )
{
// Get the color of the player who is returning the discs
var targetColor = this.gamedatas.players[ notif.args.player_id ].color;
// Make these discs blink and set them to the specified color
for( var i in notif.args.turnedOver )
{
var token = notif.args.turnedOver[ i ];
// Make the token blink 2 times
var anim = dojo.fx.chain( [
dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ),
dojo.fadeOut( {
node: 'token_'+token.x+'_'+token.y,
onEnd: function( node ) {
// Remove any color class
dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] );
// ... and add the good one
dojo.addClass( node, 'tokencolor_'+targetColor );
}
} ),
dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } )
] ); // end of dojo.fx.chain
// ... and launch the animation
anim.play();
}
},
</pre>
The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()".
9c6a8cb2c794566964cbaebf6757a4a8d58e53f8
Grade
0
30
1048
712
2014-01-14T02:59:12Z
Tim robinson
4708
/* All grades */
wikitext
text/x-wiki
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== All grades ==
* '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel).
* '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points.
* '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade.
* '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased.
* '''Archangel''': this is the Board Game Arena administrators' grade.
* '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time.
* '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...)
5953d5338df3e4a588747647198989d0eede4340
Rating
0
16
1049
184
2014-01-15T08:22:08Z
Tim robinson
4708
/* Okay, but I want to know the formula ! */
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game at a better place than a player with a higher ELO, you gain a lot of points.
* If you end the game at a better place than a player with a lower ELO, you gain less points.
* If you end the game at a worse place than a player with a lower ELO, you lose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you lose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
ELO system on BGA has some specificity:
* During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating.
* Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank).
* Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly one's used by the ELO rating system, with the following adjustments:
* First of all, if someone left a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players".
* If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
be3b5bffa0a8ad60134ce93dc6a4f93df0db1ed0
Gamehelptournay
0
143
1050
2014-02-04T15:31:51Z
Pikiou
1872
No rules were added, so I took the opportunity to thank Nosnhoj Kräm ^^
wikitext
text/x-wiki
Thanks to Nosnhoj Kräm (Eeeville) for his Tournay card descriptions used in the BGA adaptation!
ab25f7264e6489f116b85b3b93a28bbdc6055ce5
파일:BGA transparent horizontal logo.png
6
144
1051
2014-02-12T20:06:45Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:BGA transparent horizontal white logo.png
6
145
1052
2014-02-12T20:09:09Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:BGA transparent vertical logo.png
6
146
1053
2014-02-12T20:10:18Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Logos
0
147
1054
2014-02-12T20:10:37Z
Sourisdudesert
1
Created page with "On this page you can find brand assets for Board Game Arena. Please use "right click + save image as" to download needed images. == BGA transparent horizontal logo == (sho..."
wikitext
text/x-wiki
On this page you can find brand assets for Board Game Arena.
Please use "right click + save image as" to download needed images.
== BGA transparent horizontal logo ==
(should be used on a white background):
[[File:BGA transparent horizontal logo.png]]
== BGA transparent horizontal white logo ==
(should be used on a black background):
[[File:BGA transparent horizontal white logo.png]]
== BGA transparent vertical logo ==
[[File:BGA_transparent_vertical_logo.png]]
b7180517559277c310a87e737ff30450271c7977
1055
1054
2014-02-12T20:11:10Z
Sourisdudesert
1
wikitext
text/x-wiki
On this page you can find brand assets for Board Game Arena and easy way to create links to BGA.
Please use "right click + save image as" to download needed images.
== BGA transparent horizontal logo ==
(should be used on a white background):
[[File:BGA transparent horizontal logo.png]]
== BGA transparent horizontal white logo ==
(should be used on a black background):
[[File:BGA transparent horizontal white logo.png]]
== BGA transparent vertical logo ==
[[File:BGA_transparent_vertical_logo.png]]
e03e41f9b20d1d450803ebf772d56f59f8ddf39f
1060
1055
2014-02-12T20:13:07Z
Sourisdudesert
1
wikitext
text/x-wiki
On this page you can find brand assets for Board Game Arena and easy way to create links to BGA.
Please use "right click + save image as" to download needed images.
== BGA transparent horizontal logo ==
(should be used on a white background):
[[File:BGA transparent horizontal logo.png]]
== BGA transparent horizontal white logo ==
(should be used on a black background):
[[File:BGA transparent horizontal white logo.png]]
== BGA transparent vertical logo ==
[[File:BGA_transparent_vertical_logo.png]]
== BGA icon ==
16x16:
[[File:BGA logo 16.png]]
75x75:
[[File:BGA logo 75.png]]
128x128:
[[File:BGA logo 512.png]]
512x512:
[[File:BGA logo 512.png]]
3c03e32262b480d49428c87ea5980a08ec25b20d
1061
1060
2014-02-12T20:13:24Z
Sourisdudesert
1
/* BGA icon */
wikitext
text/x-wiki
On this page you can find brand assets for Board Game Arena and easy way to create links to BGA.
Please use "right click + save image as" to download needed images.
== BGA transparent horizontal logo ==
(should be used on a white background):
[[File:BGA transparent horizontal logo.png]]
== BGA transparent horizontal white logo ==
(should be used on a black background):
[[File:BGA transparent horizontal white logo.png]]
== BGA transparent vertical logo ==
[[File:BGA_transparent_vertical_logo.png]]
== BGA icon ==
16x16:
[[File:BGA logo 16.png]]
75x75:
[[File:BGA logo 75.png]]
128x128:
[[File:BGA logo 128.png]]
512x512:
[[File:BGA logo 512.png]]
a1c641bd1ba13393eec05921f99ef308d7218ec8
1071
1061
2014-02-12T21:05:52Z
Sourisdudesert
1
wikitext
text/x-wiki
On this page you can find brand assets for Board Game Arena and easy way to create links to BGA.
Please use "right click + save image as" to download needed images.
= BGA buttons =
You can use buttons below as links to BGA website:
== English ==
[[File:play_games_online_en.png]]
== French ==
[[File:play_games_online_fr.png]]
== German ==
[[File:play_games_online_de.png]]
== Spanish ==
[[File:play_games_online_es.png]]
== Italian ==
[[File:play_games_online_it.png]]
== Chinese (traditional) ==
[[File:play_games_online_zh.png]]
== Chinese (simplified) ==
[[File:play_games_online_zh_cn.png]]
== Japanese ==
[[File:play_games_online_ja.png]]
= BGA logos =
== BGA transparent horizontal logo ==
(should be used on a white background):
[[File:BGA transparent horizontal logo.png]]
== BGA transparent horizontal white logo ==
(should be used on a black background):
[[File:BGA transparent horizontal white logo.png]]
== BGA transparent vertical logo ==
[[File:BGA_transparent_vertical_logo.png]]
== BGA icon ==
16x16:
[[File:BGA logo 16.png]]
75x75:
[[File:BGA logo 75.png]]
128x128:
[[File:BGA logo 128.png]]
512x512:
[[File:BGA logo 512.png]]
3006bfb0c058b927e3507b2334b8c0f832dfd092
1074
1071
2014-02-12T21:08:32Z
Sourisdudesert
1
/* English */
wikitext
text/x-wiki
On this page you can find brand assets for Board Game Arena and easy way to create links to BGA.
Please use "right click + save image as" to download needed images.
= BGA buttons =
You can use buttons below as links to BGA website:
== Language independent ==
[[File:bga_button.png]]
== English ==
Generic:
[[File:play_games_online_en.png]]
Play it online:
[[File:play_it_on_bga_en.png]]
== French ==
[[File:play_games_online_fr.png]]
== German ==
[[File:play_games_online_de.png]]
== Spanish ==
[[File:play_games_online_es.png]]
== Italian ==
[[File:play_games_online_it.png]]
== Chinese (traditional) ==
[[File:play_games_online_zh.png]]
== Chinese (simplified) ==
[[File:play_games_online_zh_cn.png]]
== Japanese ==
[[File:play_games_online_ja.png]]
= BGA logos =
== BGA transparent horizontal logo ==
(should be used on a white background):
[[File:BGA transparent horizontal logo.png]]
== BGA transparent horizontal white logo ==
(should be used on a black background):
[[File:BGA transparent horizontal white logo.png]]
== BGA transparent vertical logo ==
[[File:BGA_transparent_vertical_logo.png]]
== BGA icon ==
16x16:
[[File:BGA logo 16.png]]
75x75:
[[File:BGA logo 75.png]]
128x128:
[[File:BGA logo 128.png]]
512x512:
[[File:BGA logo 512.png]]
e72e3c1053edce9fbbcf1c3b2be00fd1d1d94bc5
1075
1074
2014-02-12T21:14:22Z
Sourisdudesert
1
/* BGA buttons */
wikitext
text/x-wiki
On this page you can find brand assets for Board Game Arena and easy way to create links to BGA.
Please use "right click + save image as" to download needed images.
= BGA buttons =
You can use buttons below as links to BGA website.
If you need a button that is not on the list please contact us (contact@boardgamearena.com).
== Language independent ==
[[File:bga_button.png]]
== English ==
Generic:
[[File:play_games_online_en.png]]
Play it online:
[[File:play_it_on_bga_en.png]]
== French ==
[[File:play_games_online_fr.png]]
== German ==
[[File:play_games_online_de.png]]
== Spanish ==
[[File:play_games_online_es.png]]
== Italian ==
[[File:play_games_online_it.png]]
== Chinese (traditional) ==
[[File:play_games_online_zh.png]]
== Chinese (simplified) ==
[[File:play_games_online_zh_cn.png]]
== Japanese ==
[[File:play_games_online_ja.png]]
= BGA logos =
== BGA transparent horizontal logo ==
(should be used on a white background):
[[File:BGA transparent horizontal logo.png]]
== BGA transparent horizontal white logo ==
(should be used on a black background):
[[File:BGA transparent horizontal white logo.png]]
== BGA transparent vertical logo ==
[[File:BGA_transparent_vertical_logo.png]]
== BGA icon ==
16x16:
[[File:BGA logo 16.png]]
75x75:
[[File:BGA logo 75.png]]
128x128:
[[File:BGA logo 128.png]]
512x512:
[[File:BGA logo 512.png]]
06b065e7ed8f5184b92d12ca3bc0b6678a1131da
파일:BGA logo 16.png
6
148
1056
2014-02-12T20:11:45Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:BGA logo 75.png
6
149
1057
2014-02-12T20:11:53Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:BGA logo 128.png
6
150
1058
2014-02-12T20:12:01Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:BGA logo 512.png
6
151
1059
2014-02-12T20:12:08Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play games online de.png
6
152
1062
2014-02-12T21:01:39Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play games online en.png
6
153
1063
2014-02-12T21:01:50Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play games online es.png
6
154
1064
2014-02-12T21:02:00Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play games online fr.png
6
155
1065
2014-02-12T21:02:08Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
1066
1065
2014-02-12T21:02:18Z
Sourisdudesert
1
uploaded a new version of "[[File:Play games online fr.png]]"
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play games online it.png
6
156
1067
2014-02-12T21:02:28Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play games online ja.png
6
157
1068
2014-02-12T21:02:37Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play games online zh.png
6
158
1069
2014-02-12T21:02:51Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play games online zh cn.png
6
159
1070
2014-02-12T21:03:01Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Bga button.png
6
160
1072
2014-02-12T21:06:36Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Play it on bga en.png
6
161
1073
2014-02-12T21:06:47Z
Sourisdudesert
1
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Stock
0
97
1076
955
2014-02-19T21:10:34Z
Pikiou
1872
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
At first, don't forget to add "ebg/stock" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <==== HERE
],
</pre>
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_gamethemeurl+'img/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slided to, from and between your Stock controls smoothly
d7f0b2e8d1b241b8e9bd10966b85aa7828974929
1080
1076
2014-02-24T18:05:47Z
Een
3
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
At first, don't forget to add "ebg/stock" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <==== HERE
],
</pre>
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_gamethemeurl+'img/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slide to, from and between your Stock controls smoothly
dae384c29525a1d69dd67e4501a77c283b59a801
1081
1080
2014-02-24T18:22:08Z
Een
3
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
At first, don't forget to add "ebg/stock" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <==== HERE
],
</pre>
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "<div>" element (a void <div> element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_gamethemeurl+'img/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''setSelectionAppeareance( type )'''
For each stock control, you can specify a selection highlighting type:
* 'border': there will be a red border around selected items (this is the default). The attribute 'apparenceBorderWidth' can be used to manage the width of the border (in pixels).
* 'disappear': the selected item will fade out and disappear. This is useful when the selection has the effect of destroying the item.
* 'class': there will be an extra 'stockitem_selecte' css class added to the element when it is selected (and removed when unselected). You can override this class in the css file for your game.
By default this class definition is:
<pre>
.stockitem_selected {
border: 2px solid red ! important;
}
</pre>
If you want to override it for example to change the border color add this in your <game>.css file:
<pre>
.stockitem_selected {
border: 2px solid orange ! important;
}
</pre>
NB: the 'class' highlighting type has not yet been deployed on the studio - 24/02/2014. This warning will be removed after the next upgrade.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slide to, from and between your Stock controls smoothly
201df1d5f75f0a9223a3d677a435868e6887bef3
1082
1081
2014-02-24T18:33:09Z
Een
3
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
At first, don't forget to add "ebg/stock" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <==== HERE
],
</pre>
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "div" element (a void div element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_gamethemeurl+'img/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''setSelectionAppeareance( type )'''
For each stock control, you can specify a selection highlighting type:
* 'border': there will be a red border around selected items (this is the default). The attribute 'apparenceBorderWidth' can be used to manage the width of the border (in pixels).
* 'disappear': the selected item will fade out and disappear. This is useful when the selection has the effect of destroying the item.
* 'class': there will be an extra 'stockitem_selecte' css class added to the element when it is selected (and removed when unselected). You can override this class in the css file for your game.
By default this class definition is:
<pre>
.stockitem_selected {
border: 2px solid red ! important;
}
</pre>
If you want to override it for example to change the border color add this in your <game>.css file:
<pre>
.stockitem_selected {
border: 2px solid orange ! important;
}
</pre>
NB: the 'class' highlighting type has not yet been deployed on the studio - 24/02/2014. This warning will be removed after the next upgrade.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the "div" container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slide to, from and between your Stock controls smoothly
9eb6c365aa835914a123b46b22e9f45ccc16c1b9
Gamehelptournay
0
143
1077
1050
2014-02-20T00:54:42Z
Eeeville
1177
wikitext
text/x-wiki
Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation!
6087e3fd7a00dd8eab30de396f2d7e435c85a04d
1090
1077
2014-03-08T10:00:53Z
Drstuey
3099
started editing this page - will continue later
wikitext
text/x-wiki
Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation!
The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player:
# a player has filled 9 spaces with at least 2 visible prestige buildings.
# one Town Crier card more than the number of players has been revealed.
The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts.
Important notes:
* You cannot score more than 12 victory points from the same prestige building.
* If two players build the same prestige buildings there is only a single scoring.
94d79bbb06c68138ff9a1a1099f2978b9c760473
1091
1090
2014-03-09T09:53:41Z
Drstuey
3099
details of prestige buildings
wikitext
text/x-wiki
Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation!
The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player:
# A player has filled 9 spaces with at least 2 visible prestige buildings.
# One Town Crier card more than the number of players has been revealed.
The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts.
Important notes:
* You cannot score more than 12 victory points from the same prestige building.
* If two players build the same prestige building there is only a single scoring.
===Details of prestige buildings===
'''Yellow:'''
*'''Belfry''': per set (1 yellow + 1 white + 1 red) of buildings or characters
*'''City Hall''': per yellow citizen (2x)
*'''Cloth Hall''': per yellow building or character (2x)
*'''Mint''': per set of 4 deniers (2x)
*'''Tour des Six''': per character (2x)
'''White:'''
*'''Cathedral''': only the player who builds it earns 8 PPs.
*'''La Madeleine''': per prestige building (2x)
*'''Saint-Brice''': per set (1 yellow + 1 white + 1 red) of buildings or characters
*'''Saint-Jacques''': per white building or character (2x)
*'''Saint-Nicolas''': per set of citizens you own (1 yellow +1 white +1 red)
*'''Saint-Quentin''': per white citizen (2x)
'''Red:'''
*'''Pont des Trous''': per set (1 yellow + 1 white + 1 red) of citizens
*'''Porte de la Vigne''': per red citizen (2x)
*'''Tour d’Arras''': per white and yellow building (2x)
*'''Tour Henry VIII''': per rampart built (2x)
*'''Tour Saint-Georges''': per red card building or character (2x)
aba76f1199acfd1fafbb145b912989a43e9bcb0c
Faq
0
3
1078
1028
2014-02-22T19:51:24Z
Een
3
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple accounts and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think some player has had bad behavior during a game, you can give him a at the end of the game.
If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures.
a1b0dbea7f9cfbcb77d9cbd8dcf02d3c641cb263
Game interface logic: yourgamename.js
0
88
1079
1009
2014-02-24T17:49:33Z
Een
3
/* Scoring dialogs */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ).play();
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
You can also use three extra attributes in the parameter array for the notification:
<pre>
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table,
"header" => '<div>Some header</div>',
"footer" => '<div>Some footer</div>',
"closelabel" => clienttranslate( "Closing button label" )
) );
</pre>
*'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors)
*'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names)
*'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update.
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
'''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
2a4582a2f5ebf347239e3414d23aaa78dee2bff1
1097
1079
2014-03-19T10:51:16Z
Sourisdudesert
1
/* Animations */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
You can also use three extra attributes in the parameter array for the notification:
<pre>
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table,
"header" => '<div>Some header</div>',
"footer" => '<div>Some footer</div>',
"closelabel" => clienttranslate( "Closing button label" )
) );
</pre>
*'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors)
*'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names)
*'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update.
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Reversi example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
'''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
a46f2086bc1c43aacfffaaf05d98154cc9a7954f
1099
1097
2014-03-24T17:43:35Z
Sourisdudesert
1
/* Adding stuff to player's panel */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
You can also use three extra attributes in the parameter array for the notification:
<pre>
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table,
"header" => '<div>Some header</div>',
"footer" => '<div>Some footer</div>',
"closelabel" => clienttranslate( "Closing button label" )
) );
</pre>
*'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors)
*'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names)
*'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update.
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Gomoku example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
'''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
3edb1b2de886971149bb7afa955790ee664eae63
Grade
0
30
1083
1048
2014-02-28T22:27:16Z
Da man
5122
/* All grades */
wikitext
text/x-wiki
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== All grades ==
* '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel).
* '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points.
* '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade.
* '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased.
* '''Archangel''': this is the Board Game Arena administrators' grade.
* '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time.
* '''Demon''': The grade we give to people when they post things in our forums that we don't really like to hear.. like... how bad administrators we are. Yes, we use censorship... if you don't like we ban you for some days (or forever ...)
d61494b57e4426dac356ecc0045b330d4e5ef205
Gamehelppuertorico
0
23
1084
80
2014-03-02T10:26:22Z
Een
3
wikitext
text/x-wiki
== Goal ==
Be the player with the most victory points at the end of the game by collecting:
* victory points earned for buildings
* victory point tokens earned at the captain phase
* conditional victory points earned at the end of the game for occupied large buildings
In case of a tie, the player owning the most doubloons and goods is the winner.
== Rules summary ==
The game is played over several rounds.
At the start of a round, the governor selects a role, then each player in turn selects a role.
At the end of the round, the governor token moves to the next player.
When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege.
Available roles are the following:
* Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations.
* Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations.
* Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet.
* Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available.
* Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available.
* Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship.
* Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none.
Please also note that occupied violet buildings have modifier effects for role actions.
End of game happens at the end of the round for which one of the following events comes to pass :
* there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase
* the last victory point token has been earned during the captain phase
* at least one of the players built on his 12th and last free space in the city.
== Playing online ==
Choosing a role : click on the role of your choice in the list on the right of your game board.
* Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page).
* Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege.
* Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel.
* Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated.
* Builder role : click on the building that you want to buy. Placement on your board is automated.
* Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame.
* Prospector role : doubloon is earned immediately.
Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse.
== 'Balanced game' variant ==
This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page].
* The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons
* Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected three roles and the opponent has selected two (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
So it avoids the consecutive selection of two roles by the same player that happens on a change of round with the classic two player game.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
4af14d346dd971fe509fdbba835b794d1148c492
1085
1084
2014-03-02T10:27:41Z
Een
3
/* Two players variant */
wikitext
text/x-wiki
== Goal ==
Be the player with the most victory points at the end of the game by collecting:
* victory points earned for buildings
* victory point tokens earned at the captain phase
* conditional victory points earned at the end of the game for occupied large buildings
In case of a tie, the player owning the most doubloons and goods is the winner.
== Rules summary ==
The game is played over several rounds.
At the start of a round, the governor selects a role, then each player in turn selects a role.
At the end of the round, the governor token moves to the next player.
When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege.
Available roles are the following:
* Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations.
* Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations.
* Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet.
* Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available.
* Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available.
* Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship.
* Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none.
Please also note that occupied violet buildings have modifier effects for role actions.
End of game happens at the end of the round for which one of the following events comes to pass :
* there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase
* the last victory point token has been earned during the captain phase
* at least one of the players built on his 12th and last free space in the city.
== Playing online ==
Choosing a role : click on the role of your choice in the list on the right of your game board.
* Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page).
* Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege.
* Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel.
* Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated.
* Builder role : click on the building that you want to buy. Placement on your board is automated.
* Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame.
* Prospector role : doubloon is earned immediately.
Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse.
== 'Balanced game' variant ==
This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page].
* The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons
* Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
2d7aca9b12d032b70bc405a63a994ec943d7f481
Gamehelptokaido
0
134
1086
998
2014-03-03T00:10:48Z
Sumner
5143
/* End of the journey */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
= Expansions =
== Cross Roads Expansion ==
Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
6d73c686ae25a635291489a1902f4e9b3d406184
1087
1086
2014-03-03T07:13:23Z
Sumner
5143
/* Expansions */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
= Expansions =
== Cross Roads Expansion ==
Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
== The New Encounters ==
This expansion adds 4 new Encounter cards. Details here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large
7b1a4cb6dc6d2bbfafc545d8a32aff644af2f7ef
1088
1087
2014-03-03T07:20:31Z
Sumner
5143
/* The New Encounters */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
= Expansions =
== Cross Roads Expansion ==
Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
== The New Encounters ==
This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large
830cea6507fbd647bbb61b278a115936ee4fbd2a
1089
1088
2014-03-03T07:26:23Z
Sumner
5143
/* Cross Roads Expansion */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
= Expansions =
== Cross Roads Expansion ==
With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added.
Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
== The New Encounters ==
This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large
7b8a2e7ec0781136dbefc471f49d6c37bdf99f67
1093
1089
2014-03-15T06:26:38Z
Diversionarchitect
5221
/* Cross Roads Expansion */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
= Expansions =
== Cross Roads Expansion ==
With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added.
Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
Note: The faces for the fortune die (gambling at the farm) has the faces: x0,x1,x2,x3,x3,x4
== The New Encounters ==
This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large
0bddf507512bf0e338c2781499f2463416bbf225
1094
1093
2014-03-15T06:27:28Z
Diversionarchitect
5221
/* Cross Roads Expansion */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
= Expansions =
== Cross Roads Expansion ==
With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added.
Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
Note: The faces for the Fortune die (for gambling at the farm) has these faces: x0,x1,x2,x3,x3,x4
== The New Encounters ==
This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large
1d23a61bd5a434ef3902015e87c1783b487f2f36
1095
1094
2014-03-15T06:27:48Z
Diversionarchitect
5221
/* Cross Roads Expansion */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
= Expansions =
== Cross Roads Expansion ==
With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added.
Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
Note: The Fortune die (for gambling at the farm) has these faces: x0,x1,x2,x3,x3,x4
== The New Encounters ==
This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large
886bfc75a19df7fd10826b09f158d27524676626
1096
1095
2014-03-15T06:28:05Z
Diversionarchitect
5221
/* Cross Roads Expansion */
wikitext
text/x-wiki
== Object of the game ==
The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible.
To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters.
==Playing the game==
The player whose Traveler is farthest behind on the road is the player who takes the next turn.
This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces.
Once he has moved his Traveler, the player receives the benefit corresponding to this type of space.
'''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players.
==Description of the spaces==
'''Farm'''
: The player earns 3 coins.
'''Hot Spring'''
: The player takes a Hot Spring card. These cards are worth 2 or 3 points.
'''Temple'''
: The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin.
'''Encounters'''
: The player draws one Encounter card and receives a bonus:
:* Shokunin - one Souvenir
:* Annaibito - one Panorama
:* Samurai - 3 points
:* Kuge - 3 coins
:* Miko - 1 point and 1 coin to the Temple (from the bank)
'''Village'''
: The player draws 3 Souvenir cards and can purchase one or more of these cards.
: Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks.
: Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection.
: As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type.
:* The first Souvenir in a set is worth 1 point.
:* The second Souvenir in a set is worth 3 points.
:* The third Souvenir in a set is worth 5 points.
:* The fourth Souvenir in a set is worth 7 points.
'''Panorama'''
: Panoramas are made of 3, 4 or 5 sections.
: When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ».
: Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card.
: '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy).
'''Inns'''
: All Travelers must stop at each Inn.
: The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points.
: The first traveler occupies the space nearest the road, and later travelers form a line after him.
: When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1.
: He can then purchase one Meal card of his choice by paying its price.
: He adds this card, face up, to his collection and places the remaining cards next to the board, face down.
: He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards.
: '''IMPORTANT:'''
:* A traveler cannot taste the same culinary specialty twice during his journey.
:* A traveler can never purchase more than one Meal card per Inn.
:* A traveler is never obliged to purchase a Meal card.
== End of the journey ==
When all of the Travelers have arrived in Edo at the last Inn, the game ends.
The travelers score additional points depending on their ranking as donors to the Temple:
* The most generous donor scores 10 points.
* The second scores 7 points.
* The third scores 4 points.
* All other donors score 2 points.
Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points.
* Gourmet - the player with the highest total face value of Meal cards.
* Collector - the player with the most Souvenir cards.
* Bather - the player with the most Hot Spring cards.
* Chatterbox - the player with the most Encounter cards.
Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama.
Note: If players are tied after the final scoring, then the player with the most achievement cards wins.
----
'''(Extracted from the English rule book)'''
= Expansions =
== Cross Roads Expansion ==
With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added.
Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4
== The New Encounters ==
This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large
1c97478bd1c3715be28d901489239d5133e5bc2a
Gamehelptroyes
0
26
1092
708
2014-03-14T22:38:05Z
Drstuey
3099
+ add the different levels of scoring for the characters
wikitext
text/x-wiki
== Goal ==
Be the player with the most victory points at the end of the game.
== Rules summary ==
(This rules summary is based on the game help written by [http://boardgamegeek.com/user/pregremlin Andrew Agard] for Board Game Geek, under Creative Commons license. Please see [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] here for details. Thank you Andrew !)
===Initial Placement===
* In clockwise order place a citizen in empty space of one building
* Continue in counter clockwise order from last player and so on until all citizens placed
===Game play===
====Phase 0: Reveal the Activity cards====
Reveal activity card for each color corresponding to current round (first 3 rounds only)
====Phase 1: Income and salaries====
Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP
====Phase 2: Assembling the workforce====
Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district
====Phase 3: Events====
Reveal top red and white or yellow Event and place to right of queue (unlimited Events)
Events take effect from left to right
* Military: start player takes 1 black die per die symbol
* Other events: see annex (can’t execute: execute as much as possible and lose 2 VP)
After Events, roll black dice and counter:
* Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once
* Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP)
* In order players must counter highest remaining until all countered
* Use any color dice. Double red dice. Can’t buy dice or use activity cubes
====Phase 4: Actions====
See below.
====Phase 5: End of the round====
Receive deniers from district
Return citizens lying on buildings to personal supplies
Return unused dice to general supply
Pass start player card left.
===Actions===
In order each player can use 1-3 matching dice for one action or pass.
Round ends when no dice available or all players have passed
May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice
====Activate Activity Card====
Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place
citizen on free space (or illustration if full) from personal supply or any board location
* 1 tradesman per player per card
* Must activate at least once if tradesman hired
* Citizens on card cannot be moved to newly freed space
Immediate effect: activation cost (round down) determines color and use of dice
Delayed effect: place cubes equal to activation cost. Use later (one cube per action)
====Construct Cathedral====
* Use 1-3 white dice to place 1-3 cubes on same-numbered construction site
* Must place on lower levels before placing in higher levels for each set of valued spaces
* Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6
====Combat Events====
* Activation cost (round down) defines dice and number of cubes to place on card
* Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners
Event countered when banners filled
* Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards.
* 2nd most cubes earns smaller reward (tied: total rounded down)
* Most cubes takes card (tied: player who placed first). Discard if neutral has most
* Marauding: rewards given, cubes removed, and then event is available again
====Place a citizen on building====
* Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value
* Shift existing citizens to right. Citizens pushed off are laid on building illustration
* If already have expelled citizen nobody can expel your citizens from that building
====Use Agriculture====
* Gain number of deniers equal to total value divided by 2 (round down)
===Pass===
* If dice still in any city square, pass and receive 2 deniers which are placed in district
* Each turn add another denier to district
==Characters scoring==
===Chretien de Troyes===
Awards citizens placed on the 3 principal buildings
* 1 VP for 3+ (4+ with 2 players)
* 3 VP for 5+ (6+ with 2 players)
* 6 VP for 7+ (8+ with 2 players)
===Urbain IV===
Awards cubes placed on the cathedral
* 1 VP for 3+ (4+ with 2 players)
* 3 VP for 5+ (6+ with 2 players)
* 6 VP for 7+ (8+ with 2 players)
===Thibaut II===
Awards deniers
* 1 VP for 6+
* 3 VP for 12+
* 6 VP for 18+
===Hugues de Payns===
Awards influence
* 1 VP for 5+
* 3 VP for 10+
* 6 VP for 15+
===Le Florentin===
Awards tradesman on the activity cards
* 1 VP for 2+
* 3 VP for 4+
* 6 VP for 6+
===Henry I===
Awards event cards
* 1 VP for 1+
* 3 VP for 3+
* 6 VP for 5+
e000835f92220c6f16d0a1a52e246e365c2f0017
Gamehelptzolkin
0
129
1098
978
2014-03-23T02:55:55Z
Sumner
5143
/* For Each Round */
wikitext
text/x-wiki
Rules are here: http://czechgames.com/files/Tzolkin_EN.pdf
== '''For Each Round''' ==
- Each player takes their turn, going around the table
- On a food day, feed your workers and take your rewards
- Advance the Calendar
== '''Player turn''' ==
- '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple)
- '''Either place workers OR pick up workers'''
-- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers
-- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either
--- Use the action where your worker was standing
--- Use a lower action on the wheel from where your worker was standing(if not
standing on a free action space,pay 1 corn for each step back)
--- Do nothing.
== '''Food Day''' ==
-'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for.
-- For each worker not fed, you lose 3 points
-'''Take Rewards'''
--''Middle of Age (Brown days)''
--- Receive items shown on the left edge of temples from step you are on and all steps below
-- ''End of Age (Teal Days)''
--- Remove all Age 1 buildings and fill spaces with Age 2 buildings/
--- Receive points shown on the right edge of temples for the step you are on.
--- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus.
== '''Advance the Calendar''' ==
If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day.
Otherwise:
- The worker on the Starting Player space returns to the player
-- If this person was not the starting player, they take the starting player marker.
-- If they were the starting player, the starting player marker is moved to the player on his left
- Advance the Tzolk'in Gear one day.
- The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears.
-- If you use this option, flip your board to dark side up.
-- This does not avoid food days.
df8f36fa1da14ce79c2df6f252a145990f5f28d2
Gamehelpkalah
0
162
1100
2014-04-08T09:29:08Z
Stst
2180
Created page with "===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called kalah. A player owns the six holes cl..."
wikitext
text/x-wiki
===EQUIPMENT===
Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called kalah.
A player owns the six holes closest to him and the kalah on his right side.
Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole.
===OBJECT===
The object of the game is to capture more stones than one's opponent.
===RULES===
At the beginning of the game, from 3 to 6 stones are placed in each hole.
Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control.
Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah.
If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured.
If the last stone falls into the player's Kalah, he must move again.
If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah.
If the opposite hole is empty, nothing is captured. A capture ends the move.
===END OF THE GAME===
The game ends:
When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent.
OR
When a player collected more half of all stones in his/her Kalah.
The player who has captured most stones is declared the winner.
===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)===
"Pie rule" - Second player can take opponent's first move and change side of the board.
"Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty.
===COMMENT FROM THE DEVELOPER (stst)===
'''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME'''
de34e78cae9854089d843dd9b32e6e461460ee89
1101
1100
2014-04-09T06:46:15Z
Stst
2180
wikitext
text/x-wiki
===EQUIPMENT===
Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah.
A player owns the six holes closest to him and the Kalah on his right side.
Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole.
===OBJECT===
The object of the game is to capture more stones than one's opponent.
===RULES===
At the beginning of the game, from 3 to 6 stones are placed in each hole.
Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control.
Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah.
If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured.
If the last stone falls into the player's Kalah, he must move again.
If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah.
If the opposite hole is empty, nothing is captured. A capture ends the move.
===END OF THE GAME===
The game ends:
When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent.
OR
When a player collected more half of all stones in his/her Kalah.
The player who has collected most stones in his/her Kalah is declared the winner.
===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)===
"Pie rule" - Second player can take opponent's first move and change side of the board.
"Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty.
===COMMENT FROM THE DEVELOPER (stst)===
'''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME'''
dd278ce076daa8be794993744bdaaebc59f8a14a
Gamehelpkalah
0
162
1102
1101
2014-04-10T04:26:55Z
Stst
2180
/* RULES */
wikitext
text/x-wiki
===EQUIPMENT===
Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah.
A player owns the six holes closest to him and the Kalah on his right side.
Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole.
===OBJECT===
The object of the game is to capture more stones than one's opponent.
===RULES===
At the beginning of the game, from 3 to 6 stones are placed in each hole.
Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control.
Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah.
If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured.
If the last stone falls into the player's Kalah, he must move again.
If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah.
If the opposite hole is empty, nothing is captured. A capture ends the move.
===END OF THE GAME===
The game ends:
When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent.
OR
When a player collected more half of all stones in his/her Kalah.
The player who has collected most stones in his/her Kalah is declared the winner.
===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)===
"Pie rule" - Second player can take opponent's first move and change side of the board.
"Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty.
===COMMENT FROM THE DEVELOPER (stst)===
'''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME'''
8beba5bfc392f48ad6ec7a1b1646ae5833f1172a
1103
1102
2014-04-10T04:27:44Z
Stst
2180
/* RULES */
wikitext
text/x-wiki
===EQUIPMENT===
Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah.
A player owns the six holes closest to him and the Kalah on his right side.
Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole.
===OBJECT===
The object of the game is to capture more stones than one's opponent.
===RULES===
At the beginning of the game, from 3 to 6 stones are placed in each hole.
Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control.
Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah.
If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured.
If the last stone falls into the player's Kalah, he must move again.
If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah.
If the opposite hole is empty, nothing is captured. A capture ends the move.
===END OF THE GAME===
The game ends:
When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent.
OR
When a player collected more half of all stones in his/her Kalah.
The player who has collected most stones in his/her Kalah is declared the winner.
===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)===
"Pie rule" - Second player can take opponent's first move and change side of the board.
"Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty.
===COMMENT FROM THE DEVELOPER (stst)===
'''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME'''
dd278ce076daa8be794993744bdaaebc59f8a14a
1104
1103
2014-04-10T07:48:00Z
Stst
2180
wikitext
text/x-wiki
===EQUIPMENT===
Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah.
A player owns the six holes closest to him and the Kalah on his right side.
Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole.
===OBJECT===
The object of the game is to capture more stones than one's opponent.
===RULES===
At the beginning of the game, from 3 to 6 stones are placed in each hole.
Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control.
Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah.
If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured.
If the last stone falls into the player's Kalah, he must move again.
If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah.
If the opposite hole is empty, nothing is captured. A capture ends the move.
===END OF THE GAME===
The game ends:
When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent.
OR
When a player collected more half of all stones in his/her Kalah.
The player who has collected most stones in his/her Kalah is declared the winner.
===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)===
"Pie rule" - Second player can take opponent's first move and change side of the board.
"Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty.
===COMMENT FROM THE DEVELOPER (stst)===
'''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME'''
8beba5bfc392f48ad6ec7a1b1646ae5833f1172a
1105
1104
2014-04-10T09:40:17Z
Stst
2180
/* VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME) */
wikitext
text/x-wiki
===EQUIPMENT===
Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah.
A player owns the six holes closest to him and the Kalah on his right side.
Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole.
===OBJECT===
The object of the game is to capture more stones than one's opponent.
===RULES===
At the beginning of the game, from 3 to 6 stones are placed in each hole.
Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control.
Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah.
If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured.
If the last stone falls into the player's Kalah, he must move again.
If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah.
If the opposite hole is empty, nothing is captured. A capture ends the move.
===END OF THE GAME===
The game ends:
When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent.
OR
When a player collected more half of all stones in his/her Kalah.
The player who has collected most stones in his/her Kalah is declared the winner.
===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)===
«Pie rule» - Second player can take opponent's first move and change side of the board.
«Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty.
===COMMENT FROM THE DEVELOPER (stst)===
'''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME'''
4fe7f391761f5d53938f87ca7d6a78c95d1acc89
1112
1105
2014-04-28T20:02:18Z
Stst
2180
/* VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME) */
wikitext
text/x-wiki
===EQUIPMENT===
Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah.
A player owns the six holes closest to him and the Kalah on his right side.
Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole.
===OBJECT===
The object of the game is to capture more stones than one's opponent.
===RULES===
At the beginning of the game, from 3 to 6 stones are placed in each hole.
Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control.
Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah.
If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured.
If the last stone falls into the player's Kalah, he must move again.
If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah.
If the opposite hole is empty, nothing is captured. A capture ends the move.
===END OF THE GAME===
The game ends:
When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent.
OR
When a player collected more half of all stones in his/her Kalah.
The player who has collected most stones in his/her Kalah is declared the winner.
===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)===
«Pie rule» - Second player can take opponent's first move and change sides of the board.
«Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty.
===COMMENT FROM THE DEVELOPER (stst)===
'''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME'''
2f516a35fa025af19ded3b509148e680b150ee45
Steps to create a BGA game
0
117
1106
957
2014-04-19T21:57:26Z
Adam badura
5433
Missing character added
wikitext
text/x-wiki
Here's a summary of the different steps you would follow when developing a game with BGA Studio.
{| class="wikitable"
|-
! Step !! How to reach this ste?p !! What happened during the step?
|-
| Initial || [[How to join BGA developer team?]] || You can choose to join an existing team / create a new project
|-
| Assigned || You choosed a game || You can start the development of the game
|-
| Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice.
|-
| Alpha || You tell us that your development is finished || "BGA review": we are reviewing your game and check if it respects [http://fr.slideshare.net/boardgamearena/bga-studio-guidelines BGA guidelines]. If not, we will ask you (and help you) to fix them.
|-
| Private beta || We give a "go" || "Publisher review": On preproduction platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer.
|-
| Public beta || The adaptation is approved by the publisher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]].
|-
| Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]].
|}
09800b383fedaa37ef8609c93cd105d61a633472
Gamehelplibertalia
0
105
1107
756
2014-04-24T15:09:05Z
Lowre
5460
/* How to Play */ Come giocare
wikitext
text/x-wiki
Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies.
== '''How to Play''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Tokens are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure.
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
Come giocare
Il gioco consiste in tre campagne, suddivise in 6 giorni. Ogni giorno ha 4 fasi :
Fase 1 : Sunrise
Fase 2 : Day
Fase 3 : Dusk
Fase 4 : Notte
Nella prima campagna , tutti i giocatori hanno un insieme casuale identico di 9 carte di equipaggio e 10 dobloni .
Fase 1 : Sunrise In questa fase , ogni giocatore sceglie segretamente una carta equipaggio da giocare . Una volta che tutti sono pronti , i giocatori rivelano i loro membri dell'equipaggio scelti e metterli sulla nave cargo dal basso a sinistra per il più alto sulla destra . Se c'è un pareggio , il numero tie breaker inferiore va sinistra superiore. Durante questa fase , tutte le azioni speciali che si svolgono durante l'alba capita da sinistra a destra .
Fase 2 : Giornata L'unica cosa che accade in questa fase è tutti i membri dell'equipaggio ad azione giorno devono prendere , in ordine crescente di rango . (più basso va prima) .
Fase 3 : Dusk Ogni equipaggio deve richiedere un token bottino da sotto la nave . I token sono scelti in ordine di rango ( l'opposto di Fase 2) diminuendo così l'equipaggio più alto rango ottenere la migliore selezione dei gettoni . Dopo un equipaggio rivendica un bottino e si risolve con la loro azione crepuscolo ( se presenti ) siano immediatamente messi in tana del loro giocatore prima della prossima bottino è affermato ( che è importante se qualcuno sta sostenendo una sciabola in seguito . ) In alcuni casi ci potrebbe essere più bottino di rivendicare quando il turno di un equipaggio di credito viene risolto il che significa che non ottengono bottino e andare al loro covo a mani vuote .
Fase 4 : Notte L'unica cosa che accade in questa fase è membri dell'equipaggio usano le loro azioni notturne . La differenza è tutti i membri dell'equipaggio nella tua tana risolvere le loro azioni notturne ogni notte . In modo che Barkeep ( la sua azione è di segnare voi 1 doblone ogni notte ) si gioca il giorno 1 della campagna in corso , vi terrà pagare ogni notte ( finché egli rimane in vita . ) Giocare le carte la sera presto !
Nota : Tutto l'equipaggio deve risolvere il più delle loro azioni possibili, anche se sfavorevole a se stessi o il loro controllo ! Il Brute potrebbe uccidere se stesso , il Cannoneer deve pagare 3 oro , anche se non ci sono equipaggi ammissibili in una tana per uccidere , il commerciante venderà il set di gioielli o mappe del tesoro se non si hanno altre serie di tesori di corrispondenza.
Dopo il 6 ° giorno della campagna , il round è finito . I giocatori risolvono tutti " fine della campagna" azioni dei membri dell'equipaggio ancora vivo nelle loro tane (sì , i membri dell'equipaggio possono essere uccisi ) . Tutti i membri dell'equipaggio utilizzati vengono rimossi dal gioco . Ogni giocatore somma il valore dei loro gettoni bottino e dobloni ( restituirli alla banca ) e sposta il proprio segnalino punteggio più avanti sulla pista . Ogni giocatore deve avere tre carte rimaste in mano . Questi riporto nei prossimi 2 campagne .
Per impostazione per la prossima campagna ogni giocatore riceve 10 nuovi dobloni e aggiungere un insieme casuale identico di 6 carte equipaggio a tre membri dell'equipaggio rimasto . Così i giocatori possono avere una mano leggermente diversi l'uno dall'altro andando avanti .
Turni 2 e 3 il gioco proprio come turno 1 . Alla fine della partita il giocatore con il maggior numero di punti vittoria è il vincitore .
c133f13c9b4c50f66a04f77499b6535010ffac1d
1108
1107
2014-04-24T15:10:39Z
Lowre
5460
wikitext
text/x-wiki
Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies.
== '''How to Play''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Tokens are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure.
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
'''Come giocare'''
Il gioco consiste in tre campagne, suddivise in 6 giorni. Ogni giorno ha 4 fasi :
Fase 1 : Sunrise
Fase 2 : Day
Fase 3 : Dusk
Fase 4 : Notte
Nella prima campagna , tutti i giocatori hanno un insieme casuale identico di 9 carte di equipaggio e 10 dobloni .
Fase 1 : Sunrise In questa fase , ogni giocatore sceglie segretamente una carta equipaggio da giocare . Una volta che tutti sono pronti , i giocatori rivelano i loro membri dell'equipaggio scelti e metterli sulla nave cargo dal basso a sinistra per il più alto sulla destra . Se c'è un pareggio , il numero tie breaker inferiore va sinistra superiore. Durante questa fase , tutte le azioni speciali che si svolgono durante l'alba capita da sinistra a destra .
Fase 2 : Giornata L'unica cosa che accade in questa fase è tutti i membri dell'equipaggio ad azione giorno devono prendere , in ordine crescente di rango . (più basso va prima) .
Fase 3 : Dusk Ogni equipaggio deve richiedere un token bottino da sotto la nave . I token sono scelti in ordine di rango ( l'opposto di Fase 2) diminuendo così l'equipaggio più alto rango ottenere la migliore selezione dei gettoni . Dopo un equipaggio rivendica un bottino e si risolve con la loro azione crepuscolo ( se presenti ) siano immediatamente messi in tana del loro giocatore prima della prossima bottino è affermato ( che è importante se qualcuno sta sostenendo una sciabola in seguito . ) In alcuni casi ci potrebbe essere più bottino di rivendicare quando il turno di un equipaggio di credito viene risolto il che significa che non ottengono bottino e andare al loro covo a mani vuote .
Fase 4 : Notte L'unica cosa che accade in questa fase è membri dell'equipaggio usano le loro azioni notturne . La differenza è tutti i membri dell'equipaggio nella tua tana risolvere le loro azioni notturne ogni notte . In modo che Barkeep ( la sua azione è di segnare voi 1 doblone ogni notte ) si gioca il giorno 1 della campagna in corso , vi terrà pagare ogni notte ( finché egli rimane in vita . ) Giocare le carte la sera presto !
Nota : Tutto l'equipaggio deve risolvere il più delle loro azioni possibili, anche se sfavorevole a se stessi o il loro controllo ! Il Brute potrebbe uccidere se stesso , il Cannoneer deve pagare 3 oro , anche se non ci sono equipaggi ammissibili in una tana per uccidere , il commerciante venderà il set di gioielli o mappe del tesoro se non si hanno altre serie di tesori di corrispondenza.
Dopo il 6 ° giorno della campagna , il round è finito . I giocatori risolvono tutti " fine della campagna" azioni dei membri dell'equipaggio ancora vivo nelle loro tane (sì , i membri dell'equipaggio possono essere uccisi ) . Tutti i membri dell'equipaggio utilizzati vengono rimossi dal gioco . Ogni giocatore somma il valore dei loro gettoni bottino e dobloni ( restituirli alla banca ) e sposta il proprio segnalino punteggio più avanti sulla pista . Ogni giocatore deve avere tre carte rimaste in mano . Questi riporto nei prossimi 2 campagne .
Per impostazione per la prossima campagna ogni giocatore riceve 10 nuovi dobloni e aggiungere un insieme casuale identico di 6 carte equipaggio a tre membri dell'equipaggio rimasto . Così i giocatori possono avere una mano leggermente diversi l'uno dall'altro andando avanti .
Turni 2 e 3 il gioco proprio come turno 1 . Alla fine della partita il giocatore con il maggior numero di punti vittoria è il vincitore .
f4df15211fe2334967c8177c2019865512b8e6b5
1109
1108
2014-04-24T15:15:28Z
Lowre
5460
wikitext
text/x-wiki
Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies.
== '''How to Play''' ==
The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases:
Phase 1: Sunrise
Phase 2: Day
Phase 3: Dusk
Phase 4: Night'''
In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons.
'''''Phase 1: Sunrise'''''
In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right.
'''''Phase 2: Day'''''
The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first).
'''''Phase 3: Dusk'''''
Each crew must claim a booty token from below the ship. Tokens are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed.
'''''Phase 4: Night'''''
The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early!
Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure.
After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns.
To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward.
Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner.
1db47195e1202cd4d33fe0ee8d989c0b20b42c52
Gamehelpeightmastersrevenge
0
163
1110
2014-04-26T01:07:10Z
Jinnh
4158
Created page with "Overview and aim of the game 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to ..."
wikitext
text/x-wiki
Overview and aim of the game
8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA).
You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons
are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard
to deal damage to him.
As soon as his ‘’health‘’ marker reaches the last space of his life track (whose length depends of the number
of players), he is out of the game.
The last surviving player wins the fight.
d22dc9606ab12588626e4484a0a5d397f5804020
1111
1110
2014-04-26T01:15:45Z
Jinnh
4158
wikitext
text/x-wiki
Overview and aim of the game
8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA).
You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons
are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard
to deal damage to him.
As soon as his "health" marker reaches the last space of his life track (whose length depends of the number
of players), he is out of the game.
The last surviving player wins the fight.
a7b9a9eb420c0ef12ced22819d203e4a3fded472
1138
1111
2014-06-06T09:05:16Z
Sawyer einherjar
5056
wikitext
text/x-wiki
===Overview and aim of the game===
8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA).
You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons
are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard
to deal damage to him.
As soon as his "health" marker reaches the last space of his life track (whose length depends of the number
of players), he is out of the game.
The last surviving player wins the fight.
====Turn break down====
=====Active player (attacker)=====
The active player can choose to perform one of the following actions:
Draw 2 cards (or 1 card if he or she already has 3 cards in hand due to having a handsize limit of 4 cards).
After drawing cards the active player may move one token, in his or her area, to an adjacent field.
''Or''
Perform an attack! In order to do so the active player has to place a card from his/her hand in play. This card has to be put adjacent to the two cards already in play. The card that is not adjacent to the new card will be discarded and is the card that performs the attack.
Now 5 steps take place:
# Apply token effect (if any).
# Check if the attack hits! An attack hits if the ''attacker’s attack value'' is '''exactly equal''' to the ''defender’s defense value''. (the attack value is the value created with the new card put in play; more below).
# Deal damage if the attack hits.
# Apply the effect of the discarded card.
# Play an extra turn if a pair was formed with the new card (meaning that the center numbers are equal -> 1/1 2/2 3/3 4/4 5/5).
During the extra turn a new attack can be launched or '''1''' card can be drawn. When no new pair is formed or when a card is drawn the turn is passed on the the second player.
=====Passive player (defender)=====
When the active player lauches an attack, the passive player has 3 options if certain conditions are met.
<ol>
<li>Do nothing and take the blow (shouting: "''that doesn't hurt me!''")
<li>Block the attack. You can block an attack if you meet the following condition.
<ol><li>If you have a card in play that has the same color as the card with which is attacked. (so you can block a yellow card with a
yellow card).
</li></ol>
Blocking will reduce incoming dmg with 1. However, a card used for blocking stays in its blocking state, until it is discarded (used to attack), meaning you cannot use it a second time for blocking and you cannot form a pair with it. Most important if you're attacked a second time with a card of the same color and you still have the card in the blocking area '''you will suffer 2 additional damage'''.</li>
<li>Counter the attack. You can launch a counter attack on your opponents attack when you meet 2 conditions.
<ol><li> you have in play a card with a dragon symbol</li>
<li>you have a card in your hand with a dragon symbol</li></ol>
If both conditions are met, you can form a dragon pair by playing the dragon card from your hand next to the dragon card you have in play. Be careful, as your opponent may perform a counter attack on your counter attack, if your opponent matches both conditions as well. When the attacker is not able to counter the counter attack his/her turn ends immediately and as such the effects from the card with which was attacked are not applied. (You can continue countering each other until one of you no longer has a card with a dragon symbol, to put in play).
</li>
</ol>
=====Computation of defense and attack values=====
The Attack value is equal to the sum of the numbers in the center of the couple of cards you have in play<br/>
The Defense value is equal to the sum of the numbers of both ends of the couple of cards you have in play
Example: you have a 2-4 and a 5-1 card in play. (2-4/5-1)<br/>
Thus attack value = 9 (4+5)<br/>
and defense value = 3 (2+1)
de4f65abbf17dc50f2429a6e2d4f27eff4c8619b
1140
1138
2014-06-10T14:09:58Z
Steel breeze
2275
Correction: lauches --> launches
wikitext
text/x-wiki
===Overview and aim of the game===
8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA).
You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons
are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard
to deal damage to him.
As soon as his "health" marker reaches the last space of his life track (whose length depends of the number
of players), he is out of the game.
The last surviving player wins the fight.
====Turn break down====
=====Active player (attacker)=====
The active player can choose to perform one of the following actions:
Draw 2 cards (or 1 card if he or she already has 3 cards in hand due to having a handsize limit of 4 cards).
After drawing cards the active player may move one token, in his or her area, to an adjacent field.
''Or''
Perform an attack! In order to do so the active player has to place a card from his/her hand in play. This card has to be put adjacent to the two cards already in play. The card that is not adjacent to the new card will be discarded and is the card that performs the attack.
Now 5 steps take place:
# Apply token effect (if any).
# Check if the attack hits! An attack hits if the ''attacker’s attack value'' is '''exactly equal''' to the ''defender’s defense value''. (the attack value is the value created with the new card put in play; more below).
# Deal damage if the attack hits.
# Apply the effect of the discarded card.
# Play an extra turn if a pair was formed with the new card (meaning that the center numbers are equal -> 1/1 2/2 3/3 4/4 5/5).
During the extra turn a new attack can be launched or '''1''' card can be drawn. When no new pair is formed or when a card is drawn the turn is passed on the the second player.
=====Passive player (defender)=====
When the active player launches an attack, the passive player has 3 options if certain conditions are met.
<ol>
<li>Do nothing and take the blow (shouting: "''that doesn't hurt me!''")
<li>Block the attack. You can block an attack if you meet the following condition.
<ol><li>If you have a card in play that has the same color as the card with which is attacked. (so you can block a yellow card with a
yellow card).
</li></ol>
Blocking will reduce incoming dmg with 1. However, a card used for blocking stays in its blocking state, until it is discarded (used to attack), meaning you cannot use it a second time for blocking and you cannot form a pair with it. Most important if you're attacked a second time with a card of the same color and you still have the card in the blocking area '''you will suffer 2 additional damage'''.</li>
<li>Counter the attack. You can launch a counter attack on your opponents attack when you meet 2 conditions.
<ol><li> you have in play a card with a dragon symbol</li>
<li>you have a card in your hand with a dragon symbol</li></ol>
If both conditions are met, you can form a dragon pair by playing the dragon card from your hand next to the dragon card you have in play. Be careful, as your opponent may perform a counter attack on your counter attack, if your opponent matches both conditions as well. When the attacker is not able to counter the counter attack his/her turn ends immediately and as such the effects from the card with which was attacked are not applied. (You can continue countering each other until one of you no longer has a card with a dragon symbol, to put in play).
</li>
</ol>
=====Computation of defense and attack values=====
The Attack value is equal to the sum of the numbers in the center of the couple of cards you have in play<br/>
The Defense value is equal to the sum of the numbers of both ends of the couple of cards you have in play
Example: you have a 2-4 and a 5-1 card in play. (2-4/5-1)<br/>
Thus attack value = 9 (4+5)<br/>
and defense value = 3 (2+1)
f77073d1d422c88d34737f08329bb389b20227fd
1143
1140
2014-06-11T13:56:39Z
Sawyer einherjar
5056
wikitext
text/x-wiki
===Overview and aim of the game===
8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA).
You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons
are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard
to deal damage to him.
As soon as his "health" marker reaches the last space of his life track (whose length depends of the number
of players), he is out of the game.
The last surviving player wins the fight.
====Turn break down====
=====Active player (attacker)=====
The active player can choose to perform one of the following actions:
Draw 2 cards (or 1 card if he or she already has 3 cards in hand due to having a handsize limit of 4 cards).
After drawing cards the active player may move one token, in his or her area, to an adjacent field. '''Important: A damange token that lies on a emtpy field can only be placed on an adjacent empty field, and a damage token that lies on a card can only be placed on an adjacent card!'''
''Or''
Perform an attack! In order to do so the active player has to place a card from his/her hand in play. This card has to be put adjacent to the two cards already in play. The card that is not adjacent to the new card will be discarded and is the card that performs the attack.
Now 5 steps take place:
# Apply token effect (if any).
# Check if the attack hits! An attack hits if the ''attacker’s attack value'' is '''exactly equal''' to the ''defender’s defense value''. (the attack value is the value created with the new card put in play; more below).
# Deal damage if the attack hits.
# Apply the effect of the discarded card.
# Play an extra turn if a pair was formed with the new card (meaning that the center numbers are equal -> 1/1 2/2 3/3 4/4 5/5).
During the extra turn a new attack can be launched or '''1''' card can be drawn. When no new pair is formed or when a card is drawn the turn is passed on the the second player.
=====Passive player (defender)=====
When the active player launches an attack, the passive player has 3 options if certain conditions are met.
<ol>
<li>Do nothing and take the blow (shouting: "''that doesn't hurt me!''")
<li>Block the attack. You can block an attack if you meet the following condition.
<ol><li>If you have a card in play that has the same color as the card with which is attacked. (so you can block a yellow card with a
yellow card).
</li></ol>
Blocking will reduce incoming dmg with 1. However, a card used for blocking stays in its blocking state, until it is discarded (used to attack), meaning you cannot use it a second time for blocking and you cannot form a pair with it. Most important if you're attacked a second time with a card of the same color and you still have the card in the blocking area '''you will suffer 2 additional damage'''.</li>
<li>Counter the attack. You can launch a counter attack on your opponents attack when you meet 2 conditions.
<ol><li> you have in play a card with a dragon symbol</li>
<li>you have a card in your hand with a dragon symbol</li></ol>
If both conditions are met, you can form a dragon pair by playing the dragon card from your hand next to the dragon card you have in play. Be careful, as your opponent may perform a counter attack on your counter attack, if your opponent matches both conditions as well. When the attacker is not able to counter the counter attack his/her turn ends immediately and as such the effects from the card with which was attacked are not applied. (You can continue countering each other until one of you no longer has a card with a dragon symbol, to put in play).
</li>
</ol>
=====Computation of defense and attack values=====
The Attack value is equal to the sum of the numbers in the center of the couple of cards you have in play<br/>
The Defense value is equal to the sum of the numbers of both ends of the couple of cards you have in play
Example: you have a 2-4 and a 5-1 card in play. (2-4/5-1)<br/>
Thus attack value = 9 (4+5)<br/>
and defense value = 3 (2+1)
04904199800e9d3fc3dc92a8f090f48197975fa7
Stock
0
97
1113
1082
2014-04-30T03:45:33Z
Pikiou
1872
/* Complete stock component reference */
wikitext
text/x-wiki
"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.
Stock is very flexible and is the most used component in BGA games.
Stock is used for example:
* To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
* To display items in player panels (ex: Takenoko, Amyitis, ...)
* ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.
Using stock:
* Your items are arranged nicely and sorted by type.
* When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
* Select/unselect items is a built-in functionnality.
* You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.
== Using stock: a simple example ==
Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.
At first, don't forget to add "ebg/stock" as a dependency:
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <==== HERE
],
</pre>
The stock is initialized in Javascript "setup" method like this:
<pre>
// Player hand
this.playerHand = new ebg.stock();
this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
</pre>
Explanations:
* We create a new stock object for the player hand.
* As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).
Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.
Here's how we tell stock what are the items type to display:
<pre>
// Explain there are 13 images per row in the CSS sprite image
this.playerHand.image_items_per_row = 13;
// Create cards types:
for( var color=1;color<=4;color++ )
{
for( var value=2;value<=14;value++ )
{
// Build card type id
var card_type_id = this.getCardUniqueId( color, value );
this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id );
}
}
</pre>
Explanations:
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
* Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.
Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".
From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this.
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );
In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead:
this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );
If afterwards we want to remove this card from the stock:
this.playerHand.removeFromStockById( my_card_id );
== Complete stock component reference ==
'''create( page, container_div, item_width, item_height ):'''
With create, you create a new stock component.
Parameters:
* page: the container page. Usually: "this".
* container_div: the container "div" element (a void div element in your template, with an id).
* a stock item width and height, in pixels.
(See "Hearts" example above).
'''count():'''
Return the total number of items in the stock right now.
'''addItemType( type, weight, image, image_position ):'''
Define a new type of item to the stock.
This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).
Parameters:
* type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
* weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time).
* image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.
Be careful: you must specify the image url as this:
<pre>
g_gamethemeurl+'img/yourimage.png'
</pre>
* image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.
Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:
<pre>
// Specify that there is 10 image items per row in images used in "myStockObject" control.
this.myStockObject.image_items_per_row = 10;
</pre>
'''addToStock( type, from )'''
Add an item to the stock, with the specified type.
To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).
Parameters:
* type: ID of the item type to use (as specified in "addItemType")
* from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.
Example:
<pre>
// Add a money token to the "player money" stock.
// The money token will appear on "player_id" player panel and will move to its position.
this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );
</pre>
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''addToStockWithId( type, id, from )'''
This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.
This is especially useful:
* When you need to know which item(s) has been selected by the user (see "getSelectedItems").
* When you need to remove a specific item from the stock with "removeFromStockById"
Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.
'''removeFromStock( type, to )'''
Remove an item of the specific type from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeFromStockById( id, to )'''
Remove an item with a specific ID from the stock.
"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.
'''removeAll()'''
Remove all items from the stock.
'''getPresentTypeList()'''
Return an array with all the types of items present in the stock right now.
Example:
<pre>
this.myStockControl.removeAll();
this.myStockControl.addToStock( 65 );
this.myStockControl.addToStock( 34 );
this.myStockControl.addToStock( 89 );
this.myStockControl.addToStock( 65 );
// The following returns: { 34:1, 65:1, 89:1 }
var item_types = this.myStockControl.getPresentTypeList();
</pre>
'''resetItemsPosition()'''
If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.
'''item_margin'''
By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.
Example:
<pre>
this.myStockControl.item_margin=5;
</pre>
'''changeItemsWeight( newWeights )'''
With this method you can change dynamically the weight of the item types in a stock control.
Items are immediately re-sorted with the new weight.
Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.
newWeights is an associative array: item type id => new weight.
Example:
<pre>
// Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );
</pre>
'''setSelectionMode( mode )'''
For each stock control, you can specify a selection mode:
* 0: no item can be selected by the player.
* 1: a maximum of one item can be selected by the player at the same time.
* 2: several items can be selected by the player at the same time.
'''setSelectionAppearance( type )'''
For each stock control, you can specify a selection highlighting type:
* 'border': there will be a red border around selected items (this is the default). The attribute 'apparenceBorderWidth' can be used to manage the width of the border (in pixels).
* 'disappear': the selected item will fade out and disappear. This is useful when the selection has the effect of destroying the item.
* 'class': there will be an extra 'stockitem_selecte' css class added to the element when it is selected (and removed when unselected). You can override this class in the css file for your game.
By default this class definition is:
<pre>
.stockitem_selected {
border: 2px solid red ! important;
}
</pre>
If you want to override it for example to change the border color add this in your <game>.css file:
<pre>
.stockitem_selected {
border: 2px solid orange ! important;
}
</pre>
NB: the 'class' highlighting type has not yet been deployed on the studio - 24/02/2014. This warning will be removed after the next upgrade.
'''isSelected( id )'''
Return true/false wether the specified item id has been selected or not.
'''selectItem( id )'''
Select the specified item.
'''unselectItem( id )'''
Unselect the specified item.
'''unselectAll()'''
Unselect all items of the stock.
'''onChangeSelection'''
This callback method is called when the player select/unselect an item of the stock.
You can connect this to one of your method like this:
<pre>
dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
(...)
onMyMethodToCall: function( control_name )
{
// This method is called when myStockControl selected items changed
var items = this.myStockControl.getSelectedItems();
// (do something)
},
</pre>
Note: The "control_name" argument is the ID (the "DOM" id) of the "div" container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.
'''getSelectedItems()'''
Return the list of selected items, as an array with the following format:
<pre>
[
{ type:1, id: 1001 },
{ type:1, id: 1002 },
{ type:3, id: 1003 }
...
]
</pre>
'''getUnselectedItems()'''
Same as the previous one, but return unselected item instead of seleted ones.
'''getAllItems()'''
Get all items (same format than getSelectedItems and getUnselectedItems).
'''setOverlap( horizontal_percent, vertical_percent )'''
Make items on the stock control "overlap" on each other, to save space.
By default, horizontal_overlap and vertical_overlap are 0.
When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.
vertical_overlap works differently: one items on two are shifted up.
See "Jaipur" game to see an example to use of this function.
'''onItemCreate'''
Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.
Complete example:
<pre>
// During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' );
(...)
// And here is our "setupNewCard":
setupNewCard: function( card_div, card_type_id, card_id )
{
// Add a special tooltip on the card:
this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );
// Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type
// Add some custom HTML content INSIDE the Stock item:
dojo.place( this.format_block( 'jstpl_my_card_content', {
....
} ), card_div.id );
}
</pre>
== Tips when adding/removing items to/from Stock components ==
The usual way is the following:
'''Situation A''':
When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.
'''Situation B''':
When you add a card to a stock item, and this card is coming from another stock:
* on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
* then, remove the source item with "removeFromStockById".
(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).
'''Situation C''':
When you move a card from a stock item to something that is not a stock item:
* insert the card as a classic HTML template (dojo.place / this.format_block).
* place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
* slide it to its new position with "this.slideToObject"
* remove the card from the Stock item with "removeFromStockById".
Using the methods above, your cards should slide to, from and between your Stock controls smoothly
2b1ec2b323e69ad70dab9bdbb1cda8408ab3a751
Game interface logic: yourgamename.js
0
88
1114
1099
2014-04-30T23:36:24Z
Quinarbre
4507
/* Tooltips */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''this.addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
'''this.removeTooltip( nodeId )'''
Remove a tooltip from the DOM node.
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
You can also use three extra attributes in the parameter array for the notification:
<pre>
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table,
"header" => '<div>Some header</div>',
"footer" => '<div>Some footer</div>',
"closelabel" => clienttranslate( "Closing button label" )
) );
</pre>
*'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors)
*'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names)
*'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update.
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Gomoku example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
'''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
4f79eb54f61f8719ada11d802de902007c28bccb
1136
1114
2014-06-05T16:00:00Z
Archduke
1630
/* General tips */
wikitext
text/x-wiki
This is the main file for your game interface. Here you will define:
* which actions on the page will generate calls to the server
* what happens when you get a notification for change from the server and how it will show in the browser.
== File structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* constructor: here you can define variable global to your whole interface.
* setup: this method is called when the page is refreshed, in order you can setup the game interface.
* onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state.
* onLeavingState: the method is called when leaving a game state.
* onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar.
* (utility methods): at this place you can define your utility methods
* (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item).
* setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface.
* (notification handlers): at this place you can define your notifications handlers.
== General tips ==
; this.player_id
: Id of the player on whose browser the code is running.
; this.isSpectator
: Flag set to true if the user at the table is a spectator (not a player).
: Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]].
; this.gamedatas
: Contains your initial set of datas to init the game, created at game start or game refresh (F5)
: You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't).
; this.isCurrentPlayerActive()
: Returns true if the player on whose browser the code is running is currently active (it's his turn to play)
; this.getActivePlayerId()
: Return the ID of active player, or null if we are not in a "activeplayer" type state.
; this.getActivePlayers()
: Return an array with the IDs of players that are currently active (or an empty array if there is not).
== Dojo framework ==
BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework].
The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot.
To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page.
== Access and manipulate the DOM ==
'''$('some_html_element_id')'''
The $() function is used to get some HTML element using its "id" attribute.
Example 1: modify the content of a "span" element:
<pre>
In your HTML code:
<span id="a_value_in_the_game_interface">1234</span>
In your Javascript code:
$('a_value_in_the_game_interface').innerHTML = "9999";
</pre>
Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function.
'''dojo.style'''
With dojo.style you can modify a CSS property of any HTML element of your interface.
Examples:
<pre>
// Make an element disappear
dojo.style( 'my_element', 'display', 'none' );
// Give an element a 2px border
dojo.style( 'my_element', 'borderWidth', '2px' );
// Change the background position of an element
// (very practical when you are using CSS sprite to transform an element to another)
dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' );
</pre>
Note: you must always use dojo.style to modify CSS properties of HTML elements.
Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).
'''dojo CSS classes manipulation'''
In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually).
Advantages are:
* All your CSS stuff remains in your CSS file.
* You can add/remove a list of CSS modifications with a simple function and whithout error.
* You can test if you applied the stuff to an element with "dojo.hasClass" method.
Example from "Reversi":
<pre>
// We add "possibleMove" to an element
dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' );
// In our CSS file, the class is defined as:
.possibleMove {
background-color: white;
opacity: 0.2;
filter:alpha(opacity=20); /* For IE8 and earlier */
cursor: pointer;
}
// So we've applied 4 CSS property change in one line of code.
// ... and when we need to check if a square is a possible move on client side:
if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) )
{ ... }
// ... and if we want to remove all possible moves in one line of code (see "dojo.query" method):
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
</pre>
Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :)
'''dojo.query'''
With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style.
Example:
<pre>
// All elements with class "possibleMove":
var elements = dojo.query( '.possibleMove' );
// Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"):
dojo.query( '#board .token' ).length;
</pre>
But what is really cool with dojo.query is that you can combine it with almost all methods above.
Examples:
<pre>
// Trigger a method when the mouse enter in any element with class "meeple":
dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' );
// Hide all meeples who are on the board
dojo.query( '#board .meeple' ).style( 'display', 'none' );
</pre>
'''dojo.place'''
dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values.
<pre>
// Insert your HTML code as a child of a container element
dojo.place( "<your html code>", "your_container_element_id" );
// Replace the container element with your new html
dojo.place( "<your html code>", "your_container_element_id", "replace" );
</pre>
Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place].
Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]".
'''addStyleToClass: function( cssClassName, cssProperty, propertyValue )'''
Same as dojo.style(), but for all the nodes set with the specified cssClassName
=== Animations ===
'''Dojo Animations'''
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.
Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another.
'''this.slideToObject( mobile_obj, target_obj, duration, delay )'''
You can use slideToObject to "slide" an element to a target position.
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.
The parameters are:
* mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned.
* target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide.
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START.
Example:
<pre>
this.slideToObject( "some_token", "some_place_on_board" ).play();
</pre>
'''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )'''
This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj".
Example: slide a token to some place on the board, 10 pixels to the bottom:
<pre>
this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play();
</pre>
'''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )'''
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.
slideTemporaryObject does all of this for you:
* mobile_obj_html is a piece of HTML code that represent the object to slide.
* mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.
* from is the ID of the origin of the slide.
* to is the ID of the target of the slide.
* duration/delay works exactly like in "slideToObject"
Example:
<pre>
this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' );
</pre>
'''this.slideToObjectAndDestroy: function( node, to, time, delay )'''
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel.
It works the same as this.slideToObject and takes the same arguments.
Example:
<pre>
this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 );
</pre>
'''this.fadeOutAndDestroy( node )'''
This function fade out the target HTML node, then destroy it.
Example:
<pre>
this.fadeOutAndDestroy( "a_card_that_must_disappear" );
</pre>
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.
'''Rotating elements'''
You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate.
This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element.
IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below):
<pre>
var transform;
dojo.forEach(
['transform', 'WebkitTransform', 'msTransform',
'MozTransform', 'OTransform'],
function (name) {
if (typeof dojo.body().style[name] != 'undefined') {
transform = name;
}
});
// ... and then use "transform" as the name of your CSS property for rotation
</pre>
=== Moving elements ===
'''this.placeOnObject( mobile_obj, target_obj )'''
placeOnObject works exactly like "slideToObject", except that the effect is immediate.
This is not really an animation, but placeOnObject is frequently used before starting an animation.
Example:
<pre>
// (We just created an object "my_new_token")
// Place the new token on current player board
this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id );
// Then slide it to its position on the board
this.slideToObject( "my_new_token", "a_place_on_board" ).play();
</pre>
'''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )'''
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj".
'''this.attachToNewParent( mobile_obj, target_obj )'''
With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.
Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.
Why using this method?
Changing the HTML parent of an element can be useful for the following reasons:
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.
CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect).
== Players input ==
'''dojo.connect'''
Used to associate a player event with one of your notification method.
Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"):
<pre>
dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' );
</pre>
Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else.
'''this.checkAction( "my_action_name" )'''
Usage: checkAction: function( action, nomessage )
Check if player can do the specified action by taking into account:
* current game state
* interface locking (a player can't do any action if an action is already in progress)
return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state).
return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress".
Example:
<pre>
function onClickOnGameElement( evt )
{
if( this.checkAction( "my_action" ) )
{
// Do the action
}
}
</pre>
'''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )'''
This method must be used to send a player input to the game server.
* url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html"
* parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call.
* obj_callback: must be set to "this".
* callback: a function to trigger when the server returns and everything went fine.
* callback_error: (optional and rarely used) a function to trigger when the server returns an error.
Usage:
<pre>
this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true,
arg1: myarg1,
arg2: myarg2,
...
}, this, function( result ) {
// Do some stuff after a successful call
} );
</pre>
Restricted arguments names (please don't use them):
* "action"
* "module"
* "class"
'''this.confirmationDialog()'''
Display a confirmation dialog with a yes/no choice.
We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players.
Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes );
Example:
<pre>
this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'),
dojo.hitch( this, function() {
this.ajaxcall( '/seasons/seasons/useBonus.html',
{ id:bonus_id, lock:true }, this, function( result ) {} );
} ) );
</pre>
; addEventToClass: function( cssClassName, eventName, functionName )
: Same as dojo.connect(), but for all the nodes set with the specified cssClassName
'''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )'''
You can use this method to add an action button in the main action status bar.
Arguments:
* id: a ID that should be unique in your HTML DOM document.
* label: the text of the button. Should be translatable (use _() function).
* method: the name of your method that must be triggered when the player clicks on this button.
* depreciated (optional): do not use this. Please not specify this argument or use "null".
* bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button.
You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example):
<pre>
onUpdateActionButtons: function( stateName, args )
{
console.log( 'onUpdateActionButtons: '+stateName );
if( this.isCurrentPlayerActive() )
{
switch( stateName )
{
case 'giveCards':
this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' );
break;
}
}
},
</pre>
In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method.
== Translations ==
See [[Translations]]
== Notifications ==
When something happens on the server side, your game interface Javascript logic received a notification.
Here's how you can handle these notifications on the client side.
=== Subscribe to notifications ===
Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code.
Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example):
<pre>
// In setupNotifications method:
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
</pre>
Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method.
Then, you have to define your "notif_playDisc" method:
<pre>
notif_playDisc: function( notif )
{
// Remove current possible moves (makes the board more clear)
dojo.query( '.possibleMove' ).removeClass( 'possibleMove' );
this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );
},
</pre>
In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args".
Example:
<pre>
// If you did this on PHP side:
self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) );
// On Javascript side, you can access the "myArgument" like this:
notif_myNotification: function( notif )
{
alert( "myArgument = " + notif.args.myArgument );
}
</pre>
=== Synchronous notifications ===
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so.
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.
Here's how we do this, right after our subscription:
<pre>
dojo.subscribe( 'playDisc', this, "notif_playDisc" );
this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler
</pre>
== Tooltips ==
'''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to the DOM node.
Specify 'helpString' to display some information about "what is this game element?".
Specify 'actionString' to display some information about "what happens when I click on this element?".
You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one.
Usually, _() must be used for the text to be marked for translation.
"Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines).
Example:
<pre>
this.addTooltip( 'cardcount', _('Number of cards in hand'), '' );
</pre>
'''this.addTooltipHtml( nodeId, html, delay )'''
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).
'''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )'''
Add a simple text tooltip to all the DOM nodes set with this cssClass.
IMPORTANT: all concerned nodes must have IDs to get tooltips.
'''this.addTooltipHtmlToClass( cssClass, html, delay )'''
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).
IMPORTANT: all concerned nodes must have IDs to get tooltips
'''this.removeTooltip( nodeId )'''
Remove a tooltip from the DOM node.
== Dialogs, warning messages, confirmation dialogs, ... ==
=== Warning messages ===
Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.
Ex: someone fulfill one of the end of the game condition, so this is the last turn.
'''this.showMessage( msg, type )'''
showMessage shows a message in a big rectangular area on the top of the screen of current player.
* "msg" is the string to display. It should be translated.
* "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background.
Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often.
=== Confirmation dialog ===
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.
CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online.
The situation where you should use a confirmation dialog are the following:
* It must not happen very often during a game.
* It must be linked to an action that can really "kill a game" if the player do not pay attention.
* It must be something that can be done by mistake (ex: a link on the action status bar).
How to display a confirmation dialog:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
=== Dialogs ===
At first, you shouldn't use dialogs windows.
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components.
Sometimes although, you need to display a dialog window. Here is how you do this:
<pre>
// Create the new dialog. You should store the handler in a member variable to access it later
this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") });
// Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]:
var html = this.format_block( 'jstpl_myDialogTemplate', {
arg1: myArg1,
arg2: myArg2,
...
} );
// Show the dialog
this.myDlg.attr("content", html );
this.myDlg.show();
// Now that the dialog has been displayed, you can connect your method to some dialog elements
// Example, a "close" button:
dojo.connect( $('closeDlg'), 'onclick', this, function(evt){
evt.preventDefault();
this.myDlg.hide();
} );
</pre>
Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog.
=== Scoring dialogs ===
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.
Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.
Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side.
Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow":
<pre>
// on PHP side:
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table
) );
</pre>
The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column.
Example: display an 3x3 array of strings
<pre>
$table = array(
array( "one", "two", "three" ), // This is my first line
array( "four", "five", "six" ), // This is my second line
array( "seven", "height", "nine" ) // This is my third line
);
</pre>
As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:
<pre>
$table = array(
array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ),
array( "four", "five", "six" ),
array( "seven", "height", "nine" )
);
</pre>
This is especially useful when you want to display player names with colors. Example from "Hearts":
<pre>
$firstRow = array( '' );
foreach( $players as $player_id => $player )
{
$firstRow[] = array( 'str' => '${player_name}',
'args' => array( 'player_name' => $player['player_name'] ),
'type' => 'header'
);
}
$table[] = $firstRow;
</pre>
You can also use three extra attributes in the parameter array for the notification:
<pre>
$this->notifyAllPlayers( "tableWindow", '', array(
"id" => 'finalScoring',
"title" => clienttranslate("Title of the scoring dialog"),
"table" => $table,
"header" => '<div>Some header</div>',
"footer" => '<div>Some footer</div>',
"closelabel" => clienttranslate( "Closing button label" )
) );
</pre>
*'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors)
*'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names)
*'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update.
== Update players score ==
Increase a player score (with a positive or negative number):
<pre>
this.scoreCtrl[ player_id ].incValue( score_delta );
</pre>
Set a player score to a specific value:
<pre>
this.scoreCtrl[ player_id ].setValue( new_score );
</pre>
== Players panels ==
=== Adding stuff to player's panel ===
At first, create a new "JS template" string in your template (tpl) file:
(from Gomoku example)
<pre>
var jstpl_player_board = '\<div class="cp_board">\
<div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\
</div>';
</pre>
Then, you add this piece of code in your JS file to add this template to each player panel:
<pre>
// Setting up player boards
for( var player_id in gamedatas.players )
{
var player = gamedatas.players[player_id];
// Setting up players boards if needed
var player_board_div = $('player_board_'+player_id);
dojo.place( this.format_block('jstpl_player_board', player ), player_board_div );
}
</pre>
(Note: the code above is of course from your "setup" function in your Javascript).
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id".
=== Player's panel disabling/enabling ===
'''this.disablePlayerPanel( player_id )'''
Disable given player panel (the panel background become gray).
Usually, this is used to signal that this played passes, or will be inactive during a while.
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.
'''this.enablePlayerPanel( player_id )'''
Enable a player panel that has been disabled before.
'''this.enableAllPlayerPanels()'''
Enable all player panels that has been disabled before.
== Image loading ==
See also [[Game_art:_img_directory]].
'''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load.
'''dontPreloadImage( image_file_name )'''
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.
Example of use:
<pre>
this.dontPreloadImage( 'cards.png' );
</pre>
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.
Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets.
'''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.
== Other useful stuff ==
'''dojo.hitch'''
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:
<pre>
this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() {
this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} );
} ) );
</pre>
In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called.
; updateCounters(counters)
: Useful for updating game counters in the player panel (such as resources).
: 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ]
: All counters must be referenced in this.gamedatas.counters and will be updated.
: DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'.
== BGA GUI components ==
BGA framework provides some useful ready-to-use components for the game interface:
[[Studio#BGA_Studio_game_components_reference]]
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.
Example if you are using "ebg.stock":
<pre>
define([
"dojo","dojo/_base/declare",
"ebg/core/gamegui",
"ebg/counter",
"ebg/stock" /// <=== we are using ebg.stock module
],
</pre>
85da8a14d1d8814f2f3bc9c3b3cf408ddda4394e
Gamehelpyatzy
0
122
1115
891
2014-05-03T18:14:51Z
Elizharg
5503
Yahtzee rules
wikitext
text/x-wiki
The game Yahtzee consists of 13 rounds. In each round, you roll 5 dice and then score the roll in a different category of your choice.
During a round, you can roll the dice up to three times before scoring -- the initial roll (in which you must roll all the dice), plus two optional re-rolls of any or all dice.
There are 13 scoring categories, and each must be used for one of the 13 rounds. This often results in a zero score for some categories.
The 13 scoring categories are as follows:
1-6: There is one category for each number on the die. In these categories, the score is the sum of the pips on the dice of that number. For example, a roll of 1-1-2-5-5 could be scored as 2 points in the "ones" category, 2 points in the "twos" category, 10 points in the "fives" category, or 0 points in the "threes," "fours," or "sixes." If a player scores a total of at least 63 points across these six boxes, a bonus of 35 points is added.
7. Three-Of-A-Kind: At least three dice showing the same face -- Points equal the sum of all 5 dice (not just the 3 of a kind)
8. Four-Of-A-Kind: At least four dice showing the same face -- Points equal the sum of all 5 dice (not just the 4 of a kind)
9. Full House: A three-of-a-kind and a pair -- 25 points
10. Small Straight: Four sequential dice 1-2-3-4, 2-3-4-5, or 3-4-5-6) -- 30 points
11. Large Straight: Five sequential dice (1-2-3-4-5 or 2-3-4-5-6) -- 40 points
12. Yahtzee: All five dice showing the same face -- 50 points (plus, once you have scored 50 pts for a Yahtzee, a 2nd Yahtzee gives a bonus of 100 points)
13. Chance: Any combination -- points equal the sum of all 5 dice
776d4c5ac23c727f3c05fed2bb0937dee1bfa822
Multipleaccounts
0
164
1116
2014-05-05T13:58:24Z
Sourisdudesert
1
Created page with "Board Game Arena multiple accounts policy == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the sam..."
wikitext
text/x-wiki
Board Game Arena multiple accounts policy
== The Main Rule ==
'''One BGA account = One person'''
== Playing from the same IP ==
This is '''authorized''' to play at the same table from the same IP (internet address).
The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game.
If you want to play from the same internet address than another person:
* The best option is not to play at the same table, or play at a table where you know everyone.
* If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
11e1220a86f528dfe8a53931e0317e7542087764
1117
1116
2014-05-05T13:58:40Z
Sourisdudesert
1
wikitext
text/x-wiki
== The Main Rule ==
'''One BGA account = One person'''
== Playing from the same IP ==
This is '''authorized''' to play at the same table from the same IP (internet address).
The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game.
If you want to play from the same internet address than another person:
* The best option is not to play at the same table, or play at a table where you know everyone.
* If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
72a58b9679e610d0e6ba699ae3b49c95dcfa41ea
1118
1117
2014-05-05T14:07:25Z
Sourisdudesert
1
wikitext
text/x-wiki
== The Main Rule ==
'''One BGA account = One person'''
== Playing from the same IP ==
This is '''authorized''' to play at the same table from the same IP (internet address).
The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game.
If you want to play from the same internet address than another person:
* The best option is not to play at the same table, or play at a table where you know everyone.
* If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
== Boosting your ELO by playing against yourself ==
This is the most stupid and useless thing to do on BGA.
Why? Because this is very easy to detect, and because the penalty is:
* all your secondary account are removed.
* your primary account is reset to 1500 ELO for all games.
Why this is so easy to detect:
* When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO.
* In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game.
* In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account".
* Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless.
If you have a lot of time to spend, please try to get better at this game and please do not try to cheat.
4ca2266ca185fd0f934c9a957c8559f991a14865
1121
1118
2014-05-07T01:08:18Z
Wie95
5528
/* The Main Rule */
wikitext
text/x-wiki
== The Main Rule ==
'''One BGA account = One person'''
== 重點規範 ==
'''一個 BGA 帳號 = 一個人'''
== Playing from the same IP ==
This is '''authorized''' to play at the same table from the same IP (internet address).
The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game.
If you want to play from the same internet address than another person:
* The best option is not to play at the same table, or play at a table where you know everyone.
* If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
== Boosting your ELO by playing against yourself ==
This is the most stupid and useless thing to do on BGA.
Why? Because this is very easy to detect, and because the penalty is:
* all your secondary account are removed.
* your primary account is reset to 1500 ELO for all games.
Why this is so easy to detect:
* When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO.
* In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game.
* In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account".
* Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless.
If you have a lot of time to spend, please try to get better at this game and please do not try to cheat.
3c0cb8189393503b7d0f4805f764542bc2539627
1123
1121
2014-05-10T23:38:26Z
Thanks204
5546
/* The Main Rule */
wikitext
text/x-wiki
== The Main Rule ==
'''One BGA account = One person'''
== 主要規則 ==
" 一個BGA帳號 = 一個人 "
== 重點規範 ==
'''一個 BGA 帳號 = 一個人'''
== Playing from the same IP ==
This is '''authorized''' to play at the same table from the same IP (internet address).
The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game.
If you want to play from the same internet address than another person:
* The best option is not to play at the same table, or play at a table where you know everyone.
* If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
== Boosting your ELO by playing against yourself ==
This is the most stupid and useless thing to do on BGA.
Why? Because this is very easy to detect, and because the penalty is:
* all your secondary account are removed.
* your primary account is reset to 1500 ELO for all games.
Why this is so easy to detect:
* When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO.
* In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game.
* In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account".
* Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless.
If you have a lot of time to spend, please try to get better at this game and please do not try to cheat.
9740ac53ced680550fa0e1eed23d1e370a9c16f9
1124
1123
2014-05-10T23:38:42Z
Thanks204
5546
/* 重點規範 */
wikitext
text/x-wiki
== The Main Rule ==
'''One BGA account = One person'''
== 主要規則 ==
" 一個BGA帳號 = 一個人 "
== Playing from the same IP ==
This is '''authorized''' to play at the same table from the same IP (internet address).
The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game.
If you want to play from the same internet address than another person:
* The best option is not to play at the same table, or play at a table where you know everyone.
* If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
== Boosting your ELO by playing against yourself ==
This is the most stupid and useless thing to do on BGA.
Why? Because this is very easy to detect, and because the penalty is:
* all your secondary account are removed.
* your primary account is reset to 1500 ELO for all games.
Why this is so easy to detect:
* When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO.
* In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game.
* In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account".
* Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless.
If you have a lot of time to spend, please try to get better at this game and please do not try to cheat.
7b8f8300f560377c85a28703261912807614165f
1125
1124
2014-05-12T16:29:11Z
Sourisdudesert
1
wikitext
text/x-wiki
== The Main Rule ==
'''One BGA account = One person'''
== Playing from the same IP ==
This is '''authorized''' to play at the same table from the same IP (internet address).
The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game.
If you want to play from the same internet address than another person:
* The best option is not to play at the same table, or play at a table where you know everyone.
* If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
== Boosting your ELO by playing against yourself ==
This is the most stupid and useless thing to do on BGA.
Why? Because this is very easy to detect, and because the penalty is:
* all your secondary account are removed.
* your primary account is reset to 1500 ELO for all games.
Why this is so easy to detect:
* When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO.
* In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game.
* In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account".
* Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless.
If you have a lot of time to spend, please try to get better at this game and please do not try to cheat.
43b162060f6c49a1b0ccd036ece84d982d717e6f
Help
0
4
1119
507
2014-05-06T20:36:10Z
Sawyer einherjar
5056
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena|About Board Game Arena]]
** [[About us|About us]]
** [[Club Board Game Arena|Club Board Game Arena]]
** [[Contact us|Contact us]]
=== Detailed help ===
* [[Getting started|Getting started]]
* [[Referral|Referral]]
* [[Browser support|Browser support]]
* [[Moderation and grades|Moderation and grades]]
* [[Game clock|Game clock]]
* [[Rating|Rating]]
* [[Reputation|Reputation]]
* [[Translation guidelines|Translation guidelines]]
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadöra|Armadöra]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[GamehelpDiams|Diam's]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
</td>
<td valign="top">
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphearts|Hearts]]
* [[GamehelpHex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
</td>
<td valign="top">
* [[Gamehelperudo|Perudo]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamgehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptheboss|The Boss]]
</td>
<td valign="top">
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechesnutstablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpyahtzee|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
<td>
</tr>
</table>
a07a0b0b1662d8ab90012069265c6495f0a85cfb
1120
1119
2014-05-06T20:46:07Z
Sawyer einherjar
5056
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena|About Board Game Arena]]
** [[About us|About us]]
** [[Club Board Game Arena|Club Board Game Arena]]
** [[Contact us|Contact us]]
=== Detailed help ===
* [[Getting started|Getting started]]
* [[Referral|Referral]]
* [[Browser support|Browser support]]
* [[Moderation and grades|Moderation and grades]]
* [[Game clock|Game clock]]
* [[Rating|Rating]]
* [[Reputation|Reputation]]
* [[Translation guidelines|Translation guidelines]]
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
</td>
<td valign="top">
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
</td>
<td valign="top">
* [[Gamehelperudo|Perudo]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptheboss|The Boss]]
</td>
<td valign="top">
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
<td>
</tr>
</table>
f5b50ffad8b8b64bbf003e3ded15de14d76aecaf
1122
1120
2014-05-07T09:13:45Z
Sawyer einherjar
5056
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena|About Board Game Arena]]
** [[About us|About us]]
** [[Club Board Game Arena|Club Board Game Arena]]
** [[Contact us|Contact us]]
=== Detailed help ===
* [[Getting started|Getting started]]
* [[Referral|Referral]]
* [[Browser support|Browser support]]
* [[Moderation and grades|Moderation and grades]]
* [[Game clock|Game clock]]
* [[Rating|Rating]]
* [[Reputation|Reputation]]
* [[Translation guidelines|Translation guidelines]]
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
</td>
<td valign="top">
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
</td>
<td valign="top">
* [[Gamehelperudo|Perudo]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelpsechsnimmt|Take 5!]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
211c41f5e679ff3eca9a6be8af58f2330ae8decf
1137
1122
2014-06-06T07:38:30Z
Sawyer einherjar
5056
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena|About Board Game Arena]]
** [[About us|About us]]
** [[Club Board Game Arena|Club Board Game Arena]]
** [[Contact us|Contact us]]
=== Detailed help ===
* [[Getting started|Getting started]]
* [[Referral|Referral]]
* [[Browser support|Browser support]]
* [[Moderation and grades|Moderation and grades]]
* [[Game clock|Game clock]]
* [[Rating|Rating]]
* [[Reputation|Reputation]]
* [[Translation guidelines|Translation guidelines]]
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpeightmastersrevenge|8 Master's revenge]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpgearnpiston|Gear & Piston]]
</td>
<td valign="top">
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpneutreeko|Neutreeko]]
</td>
<td valign="top">
* [[Gamehelpniagara|Niagara]]
* [[Gamehelperudo|Perudo]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
</td>
<td valign="top">
* [[Gamehelpsechsnimmt|Take 5!]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
1871b8ccddd491c0cc0236259ca9ec3ecdcc9e64
1145
1137
2014-06-12T08:51:00Z
Sawyer einherjar
5056
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena|About Board Game Arena]]
** [[About us|About us]]
** [[Club Board Game Arena|Club Board Game Arena]]
** [[Contact us|Contact us]]
=== Detailed help ===
* [[Getting started|Getting started]]
* [[Referral|Referral]]
* [[Browser support|Browser support]]
* [[Moderation and grades|Moderation and grades]]
* [[Game clock|Game clock]]
* [[Rating|Rating]]
* [[Reputation|Reputation]]
* [[Translation guidelines|Translation guidelines]]
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpeightmastersrevenge|8 Master's revenge]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpgearnpiston|Gear & Piston]]
</td>
<td valign="top">
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpneutreeko|Neutreeko]]
</td>
<td valign="top">
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
</td>
<td valign="top">
* [[Gamehelpsechsnimmt|Take 5!]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
54728048711eb85a49222ead8edcbac1af09f24d
1148
1145
2014-06-18T08:23:23Z
Sawyer einherjar
5056
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena|About Board Game Arena]]
** [[About us|About us]]
** [[Club Board Game Arena|Club Board Game Arena]]
** [[Contact us|Contact us]]
=== Detailed help ===
* [[Getting started|Getting started]]
* [[Referral|Referral]]
* [[Browser support|Browser support]]
* [[Moderation and grades|Moderation and grades]]
* [[Game clock|Game clock]]
* [[Rating|Rating]]
* [[Reputation|Reputation]]
* [[Translation guidelines|Translation guidelines]]
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpeightmastersrevenge|8 Master's revenge]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpgearnpiston|Gear & Piston]]
</td>
<td valign="top">
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpneutreeko|Neutreeko]]
</td>
<td valign="top">
* [[Gamehelpniagara|Niagara]]
* [[Gamehelperudo|Perudo]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
</td>
<td valign="top">
* [[Gamehelptargi|Targi]]
* [[Gamehelpsechsnimmt|Take 5!]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
</td>
<td valign="top">
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
a76a8805eeb0635c6ea49a7fd21be31107a1aa7e
Game clock
0
15
1126
164
2014-05-20T09:40:27Z
Googol
5621
/* Running out of time */ goes > go
wikitext
text/x-wiki
[[Category:Help]]
On '''Board Game Arena''' you are playing "live" (real time). That means you have an allotted delay to play your moves.
Most of the time, your initial delay at the beginning of a game is '''3 minutes'''. During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game.
== Time to think ==
Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page.
== Game speed ==
Table administrator can make a choice between 4 game speed profile:
* Fast
* Normal
* Slow
* Without time limit
The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing.
Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing.
== Running out of time ==
As soon as you run out of time, you get a clock penalty.
If you go over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ...
== Move time limit ==
In addition to your classical time to think, you have a limited time alloted for each move.
When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you go over this limit, you become eligible to be expelled from the game.
== "My opponent is too slow" ==
Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so.
== "I would like to think a little" ==
If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page.
Thus, your opponents will receive a message and won't be thinking you are away from keyboard.
Clicking on this link is not mandatory, but we encourage its use for courtesy.
b9ac00f7332fd2be8d85158ad5dac40b230bf01a
Rating
0
16
1127
1049
2014-05-20T09:47:43Z
Googol
5621
/* How many points do I gain / lose for each game ? */ changed at...place to in...position and less to fewer
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game in a better position than a player with a higher ELO, you gain a lot of points.
* If you end the game in a better position than a player with a lower ELO, you gain fewer points.
* If you end the game in a worse position than a player with a lower ELO, you lose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO.
* The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress, you lose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
ELO system on BGA has some specificity:
* During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating.
* Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank).
* Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly one's used by the ELO rating system, with the following adjustments:
* First of all, if someone left a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players".
* If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
642c5ea7c50e35e5127287c25e46ceac8c2ce09f
1128
1127
2014-05-20T09:52:57Z
Googol
5621
/* Some advice */ General tidying up of phraseology.
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game in a better position than a player with a higher ELO, you gain a lot of points.
* If you end the game in a better position than a player with a lower ELO, you gain fewer points.
* If you end the game in a worse position than a player with a lower ELO, you lose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and better for your ELO.
* Game rank is very important when calculating the ELO. This is the reason it is important to continue fighting for minor places in the game even if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied.
ELO system on BGA has some specificity:
* During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating.
* Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank).
* Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly one's used by the ELO rating system, with the following adjustments:
* First of all, if someone left a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players".
* If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
07e3fee5f1846a06143021ceced83b9923f9ef5a
1129
1128
2014-05-20T10:08:46Z
Googol
5621
/* How is my ELO ranking computed ? */ Rephrased for clarity, and minor grammatical edits
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game in a better position than a player with a higher ELO, you gain a lot of points.
* If you end the game in a better position than a player with a lower ELO, you gain fewer points.
* If you end the game in a worse position than a player with a lower ELO, you lose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and better for your ELO.
* Game rank is very important when calculating the ELO. This is the reason it is important to continue fighting for minor places in the game even if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system's main principle is the following: the ELO points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same ELO, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. ELO points gains and losses will, over time, tend to adjust the ELO rating of each player to reflect the actual probability that either of them will win a particular encounter.
Some changes have been made to the ELO system used on BGA:
* During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points in each game. This way, your ELO rating converges faster to you "natural" rating.
* The original ELO rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent below you (in game rank) and that you lose a 2-player game against each opponent ahead of you (in game rank).
* Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly one's used by the ELO rating system, with the following adjustments:
* First of all, if someone left a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players".
* If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
e83b9fa0d82fc973e9c0577970f8d600c9dba9e5
1130
1129
2014-05-20T10:12:24Z
Googol
5621
/* Okay, but I want to know the formula ! */ Verb tense and wording changes
wikitext
text/x-wiki
[[Category:Help]]
== What is ELO rating ? ==
Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png.
Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png.
If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game.
== How many points do I gain / lose for each game ? ==
ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples:
* If you end the game in a better position than a player with a higher ELO, you gain a lot of points.
* If you end the game in a better position than a player with a lower ELO, you gain fewer points.
* If you end the game in a worse position than a player with a lower ELO, you lose a lot points.
* And so on...
== Some advice ==
* There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and better for your ELO.
* Game rank is very important when calculating the ELO. This is the reason it is important to continue fighting for minor places in the game even if you think you can't win.
* The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players.
* When you are the first player to quit a game in progress you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent.
== How is my ELO ranking computed ? ==
The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess.
The ELO system's main principle is the following: the ELO points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same ELO, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. ELO points gains and losses will, over time, tend to adjust the ELO rating of each player to reflect the actual probability that either of them will win a particular encounter.
Some changes have been made to the ELO system used on BGA:
* During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points in each game. This way, your ELO rating converges faster to you "natural" rating.
* The original ELO rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent below you (in game rank) and that you lose a 2-player game against each opponent ahead of you (in game rank).
* Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game.
== Okay, but I want to know the formula ! ==
The formula is exactly the one used by the ELO rating system, with the following adjustments:
* First of all, if someone leaves a game for any reason this game is not taken into account by the ELO rating system.
* K=60 for the first 30 games, K=40 afterwards.
* K is multiplied by (N/2) for N-player games. If N exceeds the "advised number of players" for this game, K is multiplied by (A/2), where A is the "advised number of players".
* If 2 players have a rating difference greater than 600, we consider that their ELO difference is 600.
== Good players, Experts, Masters ==
* Good players: > 1600 ELO
* Experts: > 1800 ELO
* Masters: > 2000 ELO
5d77480881080a0400e23a827e79ab09f55cf0be
Reputation
0
17
1131
904
2014-05-20T10:13:56Z
Googol
5621
/* How to increase my reputation / what makes my reputation decrease ? */ evolved > changes
wikitext
text/x-wiki
[[Category:Help]]
== What is reputation ? ==
On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance.
To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items:
* Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png)
* % of games you finished
* % of games you finished with no clock penalties
Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits.
== How to increase my reputation / what makes my reputation decrease ? ==
At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks.
* a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player.
* a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player.
You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change.
As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player.
By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information.
Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up.
== Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png ==
* Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game.
* When you need some time to think, click on "I would like to think a little" link.
* Always stay calm: it's a game.
* Don't press your opponent to play if he has some time left.
* If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does.
* Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!).
* Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation.
== What are the consequences of a bad reputation ? ==
A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you.
It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents.
df9767457f600ba8c7ecf88ba7d728f09a673424
1132
1131
2014-05-20T10:17:47Z
Googol
5621
/* How to increase my reputation / what makes my reputation decrease ? */ General tidying
wikitext
text/x-wiki
[[Category:Help]]
== What is reputation ? ==
On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance.
To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items:
* Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png)
* % of games you finished
* % of games you finished with no clock penalties
Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits.
== How to increase my reputation / what makes my reputation decrease ? ==
At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks.
* a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player.
* a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player.
You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change.
As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended you leave the game or expel this player.
By nature, opinions are subjective. There is nothing we can do for you if you receive a "red thumb" for an unfair reason. However, we know by experience that this system has a lot of advantages and generally gives relevant and useful information.
Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up.
== Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png ==
* Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game.
* When you need some time to think, click on "I would like to think a little" link.
* Always stay calm: it's a game.
* Don't press your opponent to play if he has some time left.
* If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does.
* Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!).
* Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation.
== What are the consequences of a bad reputation ? ==
A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you.
It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents.
a62977944d6754893b72089ba91ef3370b0160b7
Faq
0
3
1133
1078
2014-05-20T10:23:36Z
Googol
5621
/* What if some player does something wrong? */ Changes for clarity and added "red thumb"
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do).
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple accounts and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game.
If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures.
448115c3c9d6121111339b005feb1dca28b30938
1134
1133
2014-05-22T00:50:37Z
Stealthswor
3331
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What is "turn based play?===
After your opponent takes a move, you are notified that it is your turn (via email or visiting the site). You then go to your game, take your turn, and the process repeats for another player.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple accounts and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game.
If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures.
d8baf4414c3bd3bc32dedb32a979a3385c1c4318
Gamehelptokaido
0
134
1135
1096
2014-05-24T00:02:07Z
Benthor
5302
wikitext
text/x-wiki
== Objetivo del juego ==
Los jugadores son viajeros en Japón. Seguirán la prestigiosa Tokaido e intentarán hacer del viaje una experiencia tan rica
como sea posible
Para ello, viajarán a través de magníficos paisajes, degustrán deliciosas especialidades culinarias, comprarán recuerdos,
se beneficiarán de las virtudes de las aguas termanles, y tendrán encuentros inolvidables.
'''Jugar el juego'''
El jugador cuyo viajero sea el más rezagado será quien tomará el siguiente turno.
Este jugador deberá mover a su viajero hacia el espacio abierto de su elección, pasando libremente sobre uno o más
espacios abiertos.
Una vez que haya movido su viajero, el jugador recibirá los beneficios correspondientes a es tipo de espacio.
NOTA: Algunos de los espacios en el tablero son dobles. Los espacios dobles se utilizan solo en juegos con 4 o 5
jugadores.
== Descripcion de los Espacios ==
'''Granja'''
El jugador gana 3 monedas
'''Aguas Termales'''
El jugador toma una tarjeta de Aguas Termales. Estas tarjetas vales 2 o 3 puntos.
'''Templo'''
El jugador debe donar 1, 2 o 3 monedas al templo y obtener 1 punto por cada moneda donada.
'''Encuentros'''
El jugados roba una carta de Encuentro y recibe un bono:
Shokunin - un Recuerdo
Annaibito - un Panorama
Samurai - 3 Puntos
Kuge - 3 Monedas
Miko - 1 Punto y 1 Moneda al templo (del banco)
'''Pueblo'''
El jugador roba 3 tarjetas de recuerdo y puede comprar una o más de esas tarjetas.
Cada recuerdo pertenece a uno de los 4 tipos: objetos pequeños, ropa, arte y alimentos y bebidas.
Los Recuerdos cuestan 1, 2 ó 3 monedas. Otorgan 1, 3, 5 ó 7 puntos en función de los recuerdos contenidos en la colección
del jugador.
Cuando compre tarjetas de recuerdo, agrúpelos en conjuntos; cada conjunto puede contener sólo un recuerdo de cada tipo
El primer Recuerdo en un conjunto 1.
El segundo Recuerdo en un conjunto vale 3 puntos.
El tercer Recuerdo en un conjunto vale 5 puntos.
El cuarto recuerdo en un conjunto vale 7 puntos.
'''Panorámica'''
Las panorámicas se componen de 3, 5 ó 5 secciones
Cuando un jugador se detiene en una estación panorámica,si aun no tiene ninguna tarjeta de ese tipo de panorámica, toma una
tarjeta panorámica de valor «1».
De lo contrario, toma el siguiente número en orden ascendente y anota tantos puntos como el valor de la tarjeta.
NOTA: Cada viajero puede crear una única panorámica de cada tipo; un viajero que complete una panorámica ya no puede
detenerse en los espacios correspondientes a ese tipo (Mar, Montaña o Arroz).
'''Posadas'''
Todos los viajeros deben detenerse en cada posada.
Las posadas son lugares donde los jugadores pueden comprar las tajertas de comida. Estas tienen un costo de 1, 2 ´0 3
monedas y otorgan 6 puntos de victoria.
El primer viajero ocupa el espacio más cercano a la carretera, y los viajeros posteriores forman una línea detras de él.
Cuando el primer viajero llega a una posada, roba tantas tarjetas de Comida como jugadores existan más 1.
Entonces compra la tarjeta de Comida de su elección, pagando su precio.
Añade esta tarjeta, boca arriba, a su colección y coloca las tarjetas restantes a un lado del tablero, boca abajo.
Luego debe esperar a que los otros viajeros lleguen a la posada. A su llegada, cada viajero comprará una de las tarjetas
de Comida restantes.
IMPORTANTE:
Un viajero no puede probar la misma especialidad culinaria dos veces durante su viaje.
Un viajero no puede adquirir más de una tarjeta de Comida por posada.
Un viajero no está obigado a comprar una tarjeta de Comida.
== '''Fin del Viaje''' ==
Cuando todos los viajero hayan llegado a Edo. en la última Posada, el juego termina.
Los viajeros anotan puntos adicionalres dependiendo de su clasificación como donantes en los templos.
El más generoso anota 10 puntos.
El segundo anota 7 puntos.
El tercero anota 4 puntos.
Todos los demás anotan 2 puntos.
Otorgar las siguientes tarjetas de logros a los viajeros apropiados. Cada tarjeta de logro vale 3 puntos. Si los jugadores
estan empatados en un logro, entonces cada uno recive 3 puntos.
Gastrónomo - El jugador con el valor conjunto más alto de las tarjetas de comida.
Coleccionita - El jugador con la mayor cantidad de recuerdos.
Bañista - El jugador con la mayor cantidad de tarjetas de aguas termales.
Parlanchín- El jugador con la mayor cantidad de tarjetas de encuentro.
Nota: existen otras 3 tarjetas de logro que se otorgan durante el juego. Una para cada tipo diferente de panorámica y cada
unoa se otorga al jugador que sea el primero en completar la panorámica específico.
Nota: Si los jugadores están empatados después de la puntuación final, el jugador con más tarjetas de logro gana.
( Extraído del libro de reglas Inglés )
Expansiones
Expansión Cruce de Caminos
Con esta expansión , cada estación (excepto la Posada) ofrece a los viajeros una nueva opción. Añaden también nuevos
viajeros .
Las reglas para jugar la expansión Cruce de Caminos se pueden encontrar aquí :
http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
Nota: El dado de la fortuna (para los juegos de azar en la granja ) tiene estas caras : x0, x1, x2, x3, x3, x4
Los Nuevos Encuentros
Esta expansión añade 4 nuevas tarjetas de Encuentro . La Descripción de las tarjetas está aquí :
http://boardgamegeek.com/image/145
f810808a8ea8c8fd3b83d7c96532bd7cabd8a5e8
Main game logic: yourgamename.game.php
0
86
1139
1042
2014-06-08T08:51:18Z
Archduke
1630
/* Accessing database */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]).
* Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]).
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below).
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this:
<pre>
'tie_breaker_description' => totranslate("Describe here your tie breaker formula"),
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaVisibleSystemException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
== Player elimination ==
In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end.
This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow").
Usage:
* Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state).
* In your PHP code:
self::eliminatePlayer( <player_to_eliminate_id> );
* the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now.
* When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results.
a2119e2f3cd991592b766f8dd42655766722d3e2
1146
1139
2014-06-15T21:03:48Z
Archduke
1630
/* Notify players */
wikitext
text/x-wiki
This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface.
== File Structure ==
The details on how the file is structured is described directly with comments on the code skeleton provided to you.
Basically, here's this structure:
* EmptyGame (constructor): where you define global variables.
* setupNewGame: initial setup of the game.
* getAllDatas: where you retrieve all game data during a complete reload of the game.
* getGameProgression: where you compute the game progression indicator.
* Utility functions: your utility functions.
* Player actions: the entry points for players actions.
* Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]).
* Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]).
* zombieTurn: what to do it's the turn of a zombie player.
== Accessing player informations ==
; getPlayersNumber()
: Returns the number of players playing at the table
: Note: doesn't work in setupNewGame so use count($players) instead
; getActivePlayerId()
: Get the "active_player", whatever what is the current state type.
: Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer"
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; getActivePlayerName()
: Get the "active_player" name
: Note: avoid using this method in a "multiplayer" state because it does not mean anything.
; loadPlayersBasicInfos()
: Get an associative array with generic data about players (ie: not game specific data).
: The key of the associative array is the player id.
: The content of each value is:
: * player_name
: * player_color (ex: ff0000)
; getCurrentPlayerId()
: Get the "current_player". The current player is the one from which the action originated (the one who send the request).
: '''Be careful''': It is not always the active player.
: In general, you shouldn't use this method, unless you are in "multiplayer" state.
; getCurrentPlayerName()
: Get the "current_player" name
: Be careful using this method (see above).
; getCurrentPlayerColor()
: Get the "current_player" color
: Be careful using this method (see above).
; isCurrentPlayerZombie()
: Check the "current_player" zombie status. If true, player leave the game.
== Accessing database ==
The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below.
'''IMPORTANT'''
BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed.
; DbQuery( $sql )
: This is the generic method to access the database.
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database.
: You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better.
; getUniqueValueFromDB( $sql )
: Returns a unique value from DB or null if no value is found.
: $sql must be a SELECT query.
: Raise an exception if more than 1 row is returned.
; getCollectionFromDB( $sql, $bSingleValue=false )
: Returns an associative array of rows for a sql SELECT query.
: The key of the resulting associative array is the first field specified in the SELECT query.
: The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values.
: First column must be a primary or alternate key.
: The resulting collection can be empty.
: If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B"
Example 1:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
1234 => 'myuser0',
1235 => 'myuser1'
)
</pre>
; getNonEmptyCollectionFromDB( $sql )
: Idem than previous one, but raise an exception if the collection is empty
; function getObjectFromDB( $sql )
: Returns one row for the sql SELECT query as an associative array or null if there is no result
: Raise an exception if the query return more than one row
Example:
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" );
Result:
array(
'id'=>1234, 'name'=>'myuser0', 'score'=>1
)
</pre>
; getNonEmptyObjectFromDB( $sql )
: Idem than previous one, but raise an exception if no row is found
; getObjectListFromDB( $sql, $bUniqueValue=false )
: Return an array of rows for a sql SELECT query.
: the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array).
: The result can be empty.
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.
Example 1:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" );
Result:
array(
array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ),
array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 )
)
</pre>
Example 2:
<pre>
self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true );
Result:
array(
'myuser0',
'myuser1'
)
</pre>
; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false )
: Return an associative array of associative array, from a SQL SELECT query.
: First array level correspond to first column specified in SQL query.
: Second array level correspond to second column specified in SQL query.
: If bSingleValue = true, keep only third column on result
; DbGetLastId()
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).
; DbAffectedRow()
: Return the number of row affected by the last operation
; escapeStringForDB( $string )
: You must use this function on every string type data in your database that contains unsafe data.
: (unsafe = can be modified by a player).
: This method makes sure that no SQL injection will be done through the string used.
<pre>
self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" );
Result:
array(
'id' => 1234,
'name' => 'myuser1',
'color' => 'ff0000'
)
</pre>
; function getNonEmptyObjectFromDB( $sql )
: Idem, but raise an exception if the query doesn't return exactly one row
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.
== Use globals ==
Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it.
Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods.
'''initGameStateLabels'''
This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs.
You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework.
<pre>
self::initGameStateLabels( array(
"my_first_global_variable" => 10,
"my_second_global_variable" => 11
) );
</pre>
'''setGameStateInitialValue( $value_label, $value_value )'''
Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method.
'''getGameStateValue( $value_label )'''
Retrieve the current value of a global.
'''setGameStateValue( $value_label, $value_value )'''
Set the current value of a global.
'''incGameStateValue( $value_label, $increment )'''
Increment the current value of a global. If increment is negative, decrement the value of the global.
Return the final value of the global.
== Game states and active players ==
; checkAction( $actionName, $bThrowException=true )
: Check if action is valid regarding current game state (exception if fails)
: The action is valid if it is listed as a "possibleactions" in the current game state (see game state description).
: This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game.
: if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions.
; activeNextPlayer()
: Make the next player active in the natural player order.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; activePrevPlayer()
: Make the previous player active (in the natural player order).
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->changeActivePlayer( $player_id )
: You can call this method to make any player active.
: Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this.
; $this->gamestate->getActivePlayerList()
: With this method you can retrieve the list of the active player at any time.
: During a "game" type gamestate, it will return a void array.
: During a "activeplayer" type gamestate, it will return an array with one value (the active player id).
: during a "multipleactiveplayer" type gamestate, it will return an array of the active players id.
: Note: you should only use this method is the latter case.
; $this->gamestate->setAllPlayersMultiactive()
: With this method, all playing players are made active.
: Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action.
; $this->gamestate->setPlayersMultiactive( $players, $next_state )
: Make a specific list of players active during a multiactive gamestate.
: Bare in mind it doesn't deactivate other previously active players.
: "players" is the array of player id that should be made active.
: In case "players" is empty, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state )
: During a multiactive game state, make the specified player inactive.
: Usually, you call this method during a multiactive game state after a player did his action.
: If this player was the last active player, the method trigger the "next_state" transition to go to the next game state.
; $this->gamestate->checkPossibleAction( $action )
: (rarely used)
: This works exactly like "checkAction", except that it do NOT check if current player is active.
: This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment.
: Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead.
== Players turn order ==
'''getNextPlayerTable()'''
Return an associative array which associate each player with the next player around the table.
In addition, key 0 is associated to the first player to play.
Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns:
<pre>
array(
1 => 2,
2 => 3,
3 => 1,
0 => 1
);
</pre>
'''getPrevPlayerTable()'''
Same as above, but the associative array associate the previous player around the table.
'''getPlayerAfter( $player_id )'''
Get player playing after given player in natural playing order.
'''getPlayerBefore( $player_id )'''
Get player playing before given player in natural playing order.
== Notify players ==
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.
'''IMPORTANT'''
Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players.
'''notifyAllPlayers( $notification_type, $notification_log, $notification_args )'''
Send a notification to all players of the game.
* notification_type:
A string that defines the type of your notification.
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).
* notification_log:
A string that defines what is to be displayed in the game log.
You can use an empty string here (""). In this case, nothing is displayed in the game log.
If you define a real string here, you should use "clienttranslate" method to make sure it can be translate.
You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array.
Note: you CAN use some HTML inside your notification log, and it is working. However:
_ pay attention to keep the log clear.
_ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument.
* notification_args:
The arguments of your notifications, as an associative array.
This array will be transmitted to the game interface logic, in order the game interface can be updated.
Complete notifyAllPlayers example (from "Reversi"):
<pre>
self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array(
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'returned_nbr' => count( $turnedOverDiscs ),
'x' => $x,
'y' => $y
) );
</pre>
You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log.
Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.
'''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )'''
Same as above, except that the notification is sent to one player only.
This method must be used each time some private information must be transmitted to a player.
== Game statistics ==
There are 2 types of statistics:
* a "player" statistic is a statistic associated to a player
* a "table" statistics is a statistic not associated to a player (global statistic for this game).
See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game.
'''initStat( $table_or_player, $name, $value, $player_id=null )'''
Create a statistic entry for the specified statistics with a default value.
This method must be called for each statistics of your game, in your setupNewGame method.
'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics.
'name' is the name of your statistics, as it has been defined in your stats.inc.php file.
'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players.
'''function setStat( $value, $name, $player_id = null )'''
Set a statistic value.
If "player_id" is not specified, setStat consider it is a TABLE statistic.
If "player_id" is specified, setStat consider it is a PLAYER statistic.
'''incStat( $delta, $name, $player_id = null )'''
Increment (or decrement) specified statistic value. Same behavior as above.
== Translations ==
See [[Translations]]
== Manage player scores and Tie breaker ==
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...
During the game, you update player's score directly by updating "player_score" field of "player" table in database.
Examples:
<pre>
// +2 points to active player
self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" );
// Set score of active player to 5
self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" );
</pre>
Note: don't forget to notify the client side in order the score control can be updated accordingly.
'''Tie breaker'''
Tie breaker is used when two players get the same score at the end of a game.
Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field.
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.
When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this:
<pre>
'tie_breaker_description' => totranslate("Describe here your tie breaker formula"),
</pre>
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.
== Reflexion time ==
; function giveExtraTime( $player_id, $specific_time=null )
: Give standard extra time to this player.
: Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options).
: You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used).
== Managing errors and exceptions ==
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored.
; throw new BgaUserException ( $error_message)
: Base class to notify a user error
: You must throw this exception when a player want to do something that he is not allowed to do.
: The error message will be shown to the player as a "red message", so it must be translated.
: Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs.
Example from Gomoku:
<pre>
throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") );
</pre>
; throw new BgaVisibleSystemException ( $error_message)
: You must throw this exception when you detect something that is not supposed to happened into your code.
: The error message is shown to the user as an "Unexpected error", in order he can report it in the forum.
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.
; throw new BgaSystemException ( $error_message)
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.
: You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened.
== Zombie mode ==
When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.
While developing your zombie mode, keep in mind that:
* Do not refer to the rules, because this situation is not planned by the rules.
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?
* The idea is NOT to develop an artificial intelligence for the game.
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it.
Each time a zombie player must play, your "zombieTurn" method is called.
Parameters:
* $state: the name of the current game state.
* $active_player: the id of the active player.
Most of the time, your zombieTurn method looks like this:
<pre>
function zombieTurn( $state, $active_player )
{
$statename = $state['name'];
if( $statename == 'myFirstGameState'
|| $statename == 'my2ndGameState'
|| $statename == 'my3rdGameState'
....
)
{
$this->gamestate->nextState( "zombiePass" );
}
else
throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename );
}
</pre>
Note that in the example above, all corresponding game state should implement "zombiePass" as a transition.
== Player elimination ==
In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end.
This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow").
Usage:
* Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state).
* In your PHP code:
self::eliminatePlayer( <player_to_eliminate_id> );
* the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now.
* When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results.
40ddee7a4cff0e731e4e95424b67b8d149f25577
Gamehelpdudo
0
165
1141
2014-06-11T13:31:38Z
Sawyer einherjar
5056
Created page with "Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately for this version of the game there seems to..."
wikitext
text/x-wiki
Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version.
Unfortunately for this version of the game there seems to be no English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version.
==Rules for Perudo (Asmodée version)==
===Goal of the Game===
''Whenever we use '''he''' it can also be read as '''she''' ''
Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner!
===Set up===
Each player starts with 5 dice which have the following faces:
# Paco icon
# value 2
# value 3
# value 4
# value 5
# value 6
Based on the amount of players the game begins with the following number of total dice:
<table border="1">
<tr>
<td> Nr. players </td>
<td> Nr. dice </td>
</tr>
<tr>
<td> 2 </td>
<td> 10 </td>
</tr>
<tr>
<td> 3 </td>
<td> 15 </td>
</tr>
<tr>
<td> 4 </td>
<td> 20 </td>
</tr>
<tr>
<td> 5 </td>
<td> 25 </td>
</tr>
<tr>
<td> 6 </td>
<td> 30 </td>
</tr>
</table>
===Round order===
All players roll their dice and check what they rolled.
The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die.
'''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico.
After a bid is placed, the turn is passed on to the player on his left, this player has 2 options:
# If he thinks that the last bid was wrong he can say "Dudo" (i doubt)
# If he thinks the last bid is reasonable, then he must increase the last bid.
====Option 1: calling Dudo====
As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/>
'''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/>
In this case the player who called Dudo was wrong to have doubted and loses one die.<br/>
'''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/>
In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die.
The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game.
====Option 2: increasing the bid====
To increase a bid a player has to choose one of the following options:
# increase the number of dice, thus the value stays the same
# increase the value on the die, thus the number of dice stays the same
Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts.
===Special rules===
The side of the die with the paco on is special
This side counts as a joker for the number of eyes when a Dudo is called.
As example: The bid on which a Dudo was called is: 9 dice with a value of 3.
<table style="width:300px" border="1">
<caption>''These dice are on the table'' </caption>
<tr><td></td><th colspan="6">Die faces</th></tr>
<tr><th>Player</th><th>Paco</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th></tr>
<tr><td>Mike</td><td>1</td><td>2</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>Lucy</td><td>0</td><td>3</td><td>1</td><td>1</td><td>0</td><td>0</td></tr>
<tr><td>John</td><td>3</td><td>0</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>Susan</td><td>1</td><td>0</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
</table>
There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers we add them to the 4 dice with a value of
3 to get a total of 9 dice with a value of 3. The Bid is thus valid and the player who called Dudo loses a die.
As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up.
Example: from 9 dice with a value of 3 one can make a bid of 5 (9/2=4.5 -rounding up->5) dice with a paco.
The Next player can now choose to either
# Increase the number of dice with a paco
# Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra.
Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. (or thus any number of dice exceeding 11)
===Palifico===
The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated).
===Optional rules===
<ol>
<li>'''Calza!'''<br/>
A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza.
If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round.
</li>
<li>'''The lost dice are visible'''<br/>
When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid.
</li></ol>
7683462768ba7fc257121936dccfd3c46cc1aa2d
1142
1141
2014-06-11T13:34:50Z
Sawyer einherjar
5056
wikitext
text/x-wiki
Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version.
Unfortunately for this version of the game there seems to be no English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version.
==Rules for Perudo (Asmodée version)==
===Goal of the Game===
''Whenever we use '''he''' it can also be read as '''she''' ''
Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner!
===Set up===
Each player starts with 5 dice which have the following faces:
# Paco
# value 2
# value 3
# value 4
# value 5
# value 6
Based on the amount of players the game begins with the following number of total dice:
<table border="1">
<tr>
<td> Nr. players </td>
<td> Nr. dice </td>
</tr>
<tr>
<td> 2 </td>
<td> 10 </td>
</tr>
<tr>
<td> 3 </td>
<td> 15 </td>
</tr>
<tr>
<td> 4 </td>
<td> 20 </td>
</tr>
<tr>
<td> 5 </td>
<td> 25 </td>
</tr>
<tr>
<td> 6 </td>
<td> 30 </td>
</tr>
</table>
===Round order===
All players roll their dice and check what they rolled.
The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die.
'''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico.
After a bid is placed, the turn is passed on to the player on his left, this player has 2 options:
# If he thinks that the last bid was wrong he can say "Dudo" (i doubt)
# If he thinks the last bid is reasonable, then he must increase the last bid.
====Option 1: calling Dudo====
As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/>
'''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/>
In this case the player who called Dudo was wrong to have doubted and loses one die.<br/>
'''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/>
In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die.
The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game.
====Option 2: increasing the bid====
To increase a bid a player has to choose one of the following options:
# increase the number of dice, thus the value stays the same
# increase the value on the die, thus the number of dice stays the same
Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts.
===Special rules===
The side of the die with the paco on is special
This side counts as a joker for the number of eyes when a Dudo is called.
As example: The bid on which a Dudo was called is: 9 dice with a value of 3.
<table style="width:300px" border="1">
<caption>''These dice are on the table'' </caption>
<tr><td></td><th colspan="6">Die faces</th></tr>
<tr><th>Player</th><th>Paco</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th></tr>
<tr><td>Mike</td><td>1</td><td>2</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>Lucy</td><td>0</td><td>3</td><td>1</td><td>1</td><td>0</td><td>0</td></tr>
<tr><td>John</td><td>3</td><td>0</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>Susan</td><td>1</td><td>0</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
</table>
There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers we add them to the 4 dice with a value of
3 to get a total of 9 dice with a value of 3. The Bid is thus valid and the player who called Dudo loses a die.
As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up.
Example: from 9 dice with a value of 3 one can make a bid of 5 (9/2=4.5 -rounding up->5) dice with a paco.
The Next player can now choose to either
# Increase the number of dice with a paco
# Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra.
Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. (or thus any number of dice exceeding 11)
===Palifico===
The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated).
===Optional rules===
<ol>
<li>'''Calza!'''<br/>
A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza.
If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round.
</li>
<li>'''The lost dice are visible'''<br/>
When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid.
</li></ol>
bafe9de8554b3d55d33f65ce792559de987f6608
1144
1142
2014-06-12T08:44:52Z
Sawyer einherjar
5056
wikitext
text/x-wiki
Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version.
Unfortunately for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version.
==Rules for Perudo (Asmodée version)==
===Goal of the Game===
''Whenever we use '''he''' it can also be read as '''she''' ''
Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner!
===Set up===
Each player starts with 5 dice which have the following faces:
# Paco
# value 2
# value 3
# value 4
# value 5
# value 6
Based on the amount of players the game begins with the following number of total dice:
<table border="1">
<tr>
<td> Nr. players </td>
<td> Nr. dice </td>
</tr>
<tr>
<td> 2 </td>
<td> 10 </td>
</tr>
<tr>
<td> 3 </td>
<td> 15 </td>
</tr>
<tr>
<td> 4 </td>
<td> 20 </td>
</tr>
<tr>
<td> 5 </td>
<td> 25 </td>
</tr>
<tr>
<td> 6 </td>
<td> 30 </td>
</tr>
</table>
===Round order===
All players roll their dice and check what they rolled.
The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die.
'''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico.
After a bid is placed, the turn is passed on to the player on his left, this player has 2 options:
# If he thinks that the last bid was wrong he can say "Dudo" (i doubt)
# If he thinks the last bid is reasonable, then he must increase the last bid.
====Option 1: calling Dudo====
As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/>
'''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/>
In this case the player who called Dudo was wrong to have doubted and loses one die.<br/>
'''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/>
In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die.
The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game.
====Option 2: increasing the bid====
To increase a bid a player has to choose one of the following options:
# increase the number of dice, thus the value stays the same
# increase the value on the die, thus the number of dice stays the same
Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts.
===Special rules===
The side of the die with the paco on is special
This side counts as a joker for the number of eyes when a Dudo is called.
As example: The bid on which a Dudo was called is: 9 dice with a value of 3.
<table style="width:300px" border="1">
<caption>''These dice are on the table'' </caption>
<tr><td></td><th colspan="6">Die faces</th></tr>
<tr><th>Player</th><th>Paco</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th></tr>
<tr><td>Mike</td><td>1</td><td>2</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>Lucy</td><td>0</td><td>3</td><td>1</td><td>1</td><td>0</td><td>0</td></tr>
<tr><td>John</td><td>3</td><td>0</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>Susan</td><td>1</td><td>0</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
</table>
There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die.
As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up.
Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco.
The Next player can now choose to either
# Increase the number of dice with a paco
# Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra.
Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11)
===Palifico===
The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated).
===Optional rules===
<ol>
<li>'''Calza!'''<br/>
A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza.
If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round.
</li>
<li>'''The lost dice are visible'''<br/>
When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid.
</li></ol>
3798116e81fb42ef58cf304c534dbef6361e61eb
Your game state machine: states.inc.php
0
90
1147
1043
2014-06-16T09:38:51Z
Archduke
1630
/* Private infos in args */
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"args" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn", <================================== HERE
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
</pre>
It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php):
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves()
);
}
</pre>
Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn :
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above).
Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn).
==== Private infos in args ====
By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic.
This is although possible to specify that some data should be sent to some specific players only:
Example 1: send an information to active player(s) only:
<pre>
function argPlayerTurn()
{
return array(
'_private' => array( // Using "_private" keyword, all data inside this array will be made private
'active' => array( // Using "active" keyword inside "_private", you select active player(s)
'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s)
)
),
'possibleMoves' => self::getPossibleMoves() // will be send to all players
);
}
</pre>
Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`)
Example 2: send an information to a specific player (<specific_player_id>) only:
<pre>
function argPlayerTurn()
{
return array(
'_private' => array( // Using "_private" keyword, all data inside this array will be made private
<specific_player_id> => array( // you select one specific player with its id
'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id>
)
),
'possibleMoves' => self::getPossibleMoves() // will be send to all players
);
}
</pre>
IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed.
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
3d5baa08e143d2d429f6e0839815cec9d68de18d
1149
1147
2014-06-18T23:04:42Z
Pikiou
1872
/* id */ potential crash on active games when ID is changed
wikitext
text/x-wiki
This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another).
Important: to understand the game state machine, the best is to read this presentation first:
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]
== Overall structure ==
The machine states is described by a PHP associative array.
Example:
<pre>
$machinestates = array(
// The initial state. Please do not modify.
1 => array(
"name" => "gameSetup",
"description" => clienttranslate("Game setup"),
"type" => "manager",
"action" => "stGameSetup",
"transitions" => array( "" => 2 )
),
// Note: ID=2 => your first state
2 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a card or pass'),
"descriptionmyturn" => clienttranslate('${you} must play a card or pass'),
"type" => "activeplayer",
"possibleactions" => array( "playCard", "pass" ),
"transitions" => array( "playCard" => 2, "pass" => 2 )
),
</pre>
== Syntax ==
=== id ===
The keys determine game states IDs (in the example above: 1 and 2).
IDs must be positive integers.
ID=1 is reserved for the first game state and should not be used (and you must not modify it).
ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it).
Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99.
Note²: You can't of course use the same ID twice.
Note: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably.
=== name ===
(mandatory)
The name of a game state is used to identify it in your game logic.
Several game states can share the same name, however this is not recommended.
PHP example:
<pre>
// Get current game state
$state = $this->gamestate->state();
if( $state['name'] == 'myGameState' )
{
...
}
</pre>
JS example:
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
case 'myGameState':
// Do some stuff at the beginning at this game state
....
break;
</pre>
=== type ===
(mandatory)
You can use 3 types of game states:
* activeplayer (1 player is active and must play)
* multipleactiveplayer (1..N players can be active and must play)
* game (no player is active. This is a transitional state to do something automatic specified by game rules)
=== description ===
(mandatory)
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.
When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side:
<pre>
"description" => clienttranslate('${actplayer} must play a card or pass'),
</pre>
In the description string, you can use ${actplayer} to refer to the active player.
You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field).
Example of custom field:
<pre>
In states.inc.php:
"description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'),
"args" => "argMyArgumentMethod"
In mygame.game.php:
function argMyArgumentMethod()
{
return array(
'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2"
);
}
</pre>
Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated).
Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state.
=== descriptionmyturn ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states type)
"descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.
In general, we have this situation:
<pre>
"description" => clienttranslate('${actplayer} can take some actions'),
"descriptionmyturn" => clienttranslate('${you} can take some actions'),
</pre>
Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player.
=== action ===
(mandatory for "game" game state type)
"action" specify a PHP method to call when entering into this game state.
Example:
<pre>
In states.inc.php:
28 => array(
"name" => "startPlayerTurn",
"description" => '',
"type" => "game",
"action" => "stStartPlayerTurn",
In mygame.game.php:
function stStartPlayerTurn()
{
// ... do something at the beginning of this game state
</pre>
Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state.
Note: a BGA convention specify that PHP method called with "action" are prefixed by "st".
=== transitions ===
(mandatory)
With "transition" you specify in which game state you can jump from a given game state.
Example:
<pre>
25 => array(
"name" => "myGameState",
"transitions" => array( "nextPlayer" => 27, "endRound" => 39 ),
....
}
</pre>
In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39.
Example to jump to ID 27:
<pre>
In mygame.game.php:
$this->gamestate->nextState( "nextPlayer" );
</pre>
Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state.
Note: if you have only 1 transition, you may give it an empty name.
Example:
<pre>
In states.inc.php:
"transitions" => array( "" => 27 ),
In mygame.game.php:
$this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
</pre>
=== possibleactions ===
(mandatory for "activeplayer" and "multipleactiveplayer" game states)
"possibleactions" defines the actions possible by the players at this game state.
By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states.
Example:
<pre>
In states.game.php:
"possibleactions" => array( "playCard", "pass" ),
In mygame.game.php:
function playCard( ...)
{
self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state.
....
In mygame.js:
playCard: function( ... )
{
if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state.
{ return ; }
....
</pre>
=== args ===
(optional)
From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state.
Example 1 : for Reversi, the list of possible moves during playerTurn state.
Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor.
Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them.
In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them.
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.
Let's see a complete example using args with « Reversi » game :
In states.inc.php, we specify some « args » argument for gamestate « playerTurn » :
<pre>
10 => array(
"name" => "playerTurn",
"description" => clienttranslate('${actplayer} must play a disc'),
"descriptionmyturn" => clienttranslate('${you} must play a disc'),
"type" => "activeplayer",
"args" => "argPlayerTurn", <================================== HERE
"possibleactions" => array( 'playDisc' ),
"transitions" => array( "playDisc" => 11, "zombiePass" => 11 )
),
</pre>
It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php):
<pre>
function argPlayerTurn()
{
return array(
'possibleMoves' => self::getPossibleMoves()
);
}
</pre>
Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn :
<pre>
onEnteringState: function( stateName, args )
{
console.log( 'Entering state: '+stateName );
switch( stateName )
{
case 'playerTurn':
this.updatePossibleMoves( args.args.possibleMoves );
break;
}
},
</pre>
Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above).
Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn).
==== Private infos in args ====
By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic.
This is although possible to specify that some data should be sent to some specific players only:
Example 1: send an information to active player(s) only:
<pre>
function argPlayerTurn()
{
return array(
'_private' => array( // Using "_private" keyword, all data inside this array will be made private
'active' => array( // Using "active" keyword inside "_private", you select active player(s)
'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s)
)
),
'possibleMoves' => self::getPossibleMoves() // will be send to all players
);
}
</pre>
Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`)
Example 2: send an information to a specific player (<specific_player_id>) only:
<pre>
function argPlayerTurn()
{
return array(
'_private' => array( // Using "_private" keyword, all data inside this array will be made private
<specific_player_id> => array( // you select one specific player with its id
'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id>
)
),
'possibleMoves' => self::getPossibleMoves() // will be send to all players
);
}
</pre>
IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed.
=== updateGameProgression ===
(optional)
IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.
At least one of your game state (any of them) must specify updateGameProgression=>true.
225c5e46634edd5833523ae11fee333980125407
Translations
0
94
1150
836
2014-06-23T22:43:35Z
Jinnh
4158
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== How to not make translators crazy ;) ==
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
<pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre>
Write instead:
<pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre>
(or the equivalent "dojo.string.substitute" in Javascript)
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings.
* The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate.
* Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY".
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
'''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead.
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
<note>Pay attention when using 'i18n' argument when translating argument for client : do NOT use same argument for both translation AND key code for client side action (like using 'card_name' to move it on player board as described in the example). It's pretty obvious in the example, but it can be very tricky when translation is made at the end of the development (which is often the case). Use explicit argument name like 'card_name_translated' by example.</note>
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new BgaUserException( self::_('You must choose 3 cards') );
// ... notice the use of BgaUserException that signals that this exception is "expected". In theory, all exception that are expected should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
6d9653cdcceabe0c9cd666fd9540128fc590cb6a
1151
1150
2014-06-23T22:43:56Z
Jinnh
4158
wikitext
text/x-wiki
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.
== How translation works? ==
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.
Before the release of the game, BGA team will do the French translation of the game.
After the release of the game, the BGA players community will translate the game in every language.
== What should be translated? ==
Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...
This does NOT include error messages that are not supposed to happened (unexpected errors).
== Focus on translating notifications ==
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.
== WARNING: how to make sure your strings will be translated ==
For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).
If your original string is not "physically" inside one of this marker, it won't be translated.
<pre>
// Examples: the following strings will be translated:
var mystring_translated = _("my string"); // JS
$mystring_translated = self::_("my string"); // PHP
$mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP
// Examples: the following strings WILL NOT be translated:
$my_string = "my string";
$not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation
$not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing
</pre>
== How to not make translators crazy ;) ==
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
<pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre>
Write instead:
<pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre>
(or the equivalent "dojo.string.substitute" in Javascript)
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings.
* The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate.
* Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY".
== On client side (Javascript) ==
On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.
Examples:
<pre>
// Get a string in player's language:
var translated = _("original english string");
// Get a string in player's language with parameter:
var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", {
p: 2,
d: 4
} );
</pre>
'''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead.
== On server side (PHP) ==
On PHP side, you can use 3 different functions to specify that a string must be translated.
'''clienttranslate( "my string to translate" ):'''
This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.
In general, you use clienttranslate:
* On your states.inc.php, for field "description" and "descriptionmyturn".
<pre>
"description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
</pre>
* On "material.inc.php", when defining texts for game material that must be displayed on client side.
<pre>
$this->card_types = array(
1 => array(
'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
</pre>
* When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
<pre>
// A game log string with no argument:
self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:
<pre>
// In the following example, we translate the game log itself, but also the "card_name" argument:
self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate
'player_id' => $player_id,
'player_name' => self::getActivePlayerName(),
'points' => $points,
'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
) );
</pre>
Pay attention when using 'i18n' argument when translating argument for client : do NOT use same argument for both translation AND key code for client side action (like using 'card_name' to move it on player board as described in the example). It's pretty obvious in the example, but it can be very tricky when translation is made at the end of the development (which is often the case). Use explicit argument name like 'card_name_translated' by example.
'''self::_( "my string to translate" ):'''
This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
* When throwing an exception because the player did a forbidden move.
<pre>
// This will display a translatable red message to the player that just do some wrong action:
throw new BgaUserException( self::_('You must choose 3 cards') );
// ... notice the use of BgaUserException that signals that this exception is "expected". In theory, all exception that are expected should be translated.
</pre>
* In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
<pre>
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
</pre>
* Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] );
</pre>
* Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.
'''totranslate( "my string to translate" ):'''
This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.
You should not use this function, except on the following cases:
* Statistics name in stats.inc.php
* Option names and option values name in gameoptions.inc.php
96da7c625db8ae8e5af16cf821169c59add4e14f
Gamehelptokaido
0
134
1152
1135
2014-07-02T12:06:32Z
Xenom
5998
wikitext
text/x-wiki
== Objetivo del juego ==
Los jugadores son viajeros en Japón. Seguirán la prestigiosa Tokaido e intentarán hacer del viaje una experiencia tan rica como sea posible.
Para ello, viajarán a través de magníficos paisajes, degustarán deliciosas especialidades culinarias, comprarán recuerdos, se beneficiarán de las virtudes de las aguas termales, y tendrán encuentros inolvidables.
==Jugar el juego==
El jugador cuyo viajero sea el más rezagado será quien tomará el siguiente turno.
Este jugador deberá mover a su viajero hacia el espacio abierto de su elección, pasando libremente sobre uno o más espacios abiertos.
Una vez que haya movido su viajero, el jugador recibirá los beneficios correspondientes a es tipo de espacio.
NOTA: Algunos de los espacios en el tablero son dobles. Los espacios dobles se utilizan solo en juegos con 4 o 5 jugadores.
===Descripción de los Espacios===
====Granja====
El jugador gana 3 monedas.
====Aguas Termales====
El jugador toma una tarjeta de Aguas Termales. Estas tarjetas valen 2 ó 3 puntos.
====Templo====
El jugador debe donar 1, 2 ó 3 monedas al templo y obtener 1 punto por cada moneda donada.
====Encuentros====
El jugados roba una carta de Encuentro y recibe un bono:
Shokunin - un Recuerdo
Annaibito - un Panorama
Samurai - 3 Puntos
Kuge - 3 Monedas
Miko - 1 Punto y 1 Moneda al templo (del banco)
====Pueblo====
El jugador roba 3 tarjetas de recuerdo y puede comprar una o más de esas tarjetas.
Cada recuerdo pertenece a uno de los 4 tipos: objetos pequeños, ropa, arte y alimentos y bebidas.
Los Recuerdos cuestan 1, 2 ó 3 monedas. Otorgan 1, 3, 5 ó 7 puntos en función de los recuerdos contenidos en la colección
del jugador.
Cuando se compran tarjetas de recuerdo, se agrupan en conjuntos; cada conjunto puede contener sólo un recuerdo de cada tipo:
El primer Recuerdo en un conjunto 1 punto.
El segundo Recuerdo en un conjunto vale 3 puntos.
El tercer Recuerdo en un conjunto vale 5 puntos.
El cuarto recuerdo en un conjunto vale 7 puntos.
====Panorámica====
Las panorámicas se componen de 3, 4 ó 5 secciones
Cuando un jugador se detiene en una estación panorámica, roba la carta de valor 1 si es la primera vez que se detiene, si ya la tiene roba la de coste superior. Es decir, la primera vez que se detiene roba la de valor 1, la segunda la de 2, la tercera la de 3, etc.
NOTA: Cada viajero puede crear una única panorámica de cada tipo; un viajero que complete una panorámica ya no puede detenerse en los espacios correspondientes a ese tipo (Mar, Montaña o Arroz).
====Posadas====
Todos los viajeros deben detenerse en cada posada.
Las posadas son lugares donde los jugadores pueden comprar las tajertas de comida. Estas tienen un costo de 1, 2 ´0 3
monedas y otorgan 6 puntos de victoria.
El primer viajero ocupa el espacio más cercano a la carretera, y los viajeros posteriores forman una línea detrás de él.
Cuando el primer viajero llega a una posada, roba tantas tarjetas de Comida como jugadores existan más 1.
Entonces compra la tarjeta de Comida de su elección, pagando su precio.
Añade esta tarjeta, boca arriba, a su colección y coloca las tarjetas restantes a un lado del tablero, boca abajo.
Luego debe esperar a que los otros viajeros lleguen a la posada. A su llegada, cada viajero comprará una de las tarjetas
de Comida restantes.
IMPORTANTE:
Un viajero no puede probar la misma especialidad culinaria dos veces durante su viaje.
Un viajero no puede adquirir más de una tarjeta de Comida por posada.
Un viajero no está obligado a comprar una tarjeta de Comida.
===Fin del Viaje===
Cuando todos los viajero hayan llegado a Edo. en la última Posada, el juego termina.
Los viajeros anotan puntos adicionales dependiendo de su clasificación como donantes en los templos.
El más generoso anota 10 puntos.
El segundo anota 7 puntos.
El tercero anota 4 puntos.
Todos los demás anotan 2 puntos.
Otorgar las siguientes tarjetas de logros a los viajeros apropiados. Cada tarjeta de logro vale 3 puntos. Si los jugadores
están empatados en un logro, entonces cada uno recibe 3 puntos.
Gastrónomo - El jugador con el valor conjunto más alto de las tarjetas de comida.
Coleccionista - El jugador con la mayor cantidad de recuerdos.
Bañista - El jugador con la mayor cantidad de tarjetas de aguas termales.
Parlanchín- El jugador con la mayor cantidad de tarjetas de encuentro.
Nota: existen otras 3 tarjetas de logro que se otorgan durante el juego. Una para cada tipo diferente de panorámica y cada una se otorga al jugador que sea el primero en completar la panorámica específica.
Nota: Si los jugadores están empatados después de la puntuación final, el jugador con más tarjetas de logro gana.
( Extraído del libro de reglas Inglés )
Expansiones
Expansión Cruce de Caminos
Con esta expansión , cada estación (excepto la Posada) ofrece a los viajeros una nueva opción. Añaden también nuevosviajeros .
Las reglas para jugar la expansión Cruce de Caminos se pueden encontrar aquí :
http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf
Nota: El dado de la fortuna (para los juegos de azar en la granja ) tiene estas caras : x0, x1, x2, x3, x3, x4
Los Nuevos Encuentros
Esta expansión añade 4 nuevas tarjetas de Encuentro . La Descripción de las tarjetas está aquí :
http://boardgamegeek.com/image/145
8470092b2b13eae69c5febc2132ca6a85562b973
Help
0
4
1153
1148
2014-07-04T10:34:36Z
Sawyer einherjar
5056
the hyperlink to perduo was fault
wikitext
text/x-wiki
An issue? A question?
* [[Faq|Frequently asked questions]] could probably help you.
* [http://forum.boardgamearena.com Forums] are also helpful to get information.
== Help contents ==
* [[Faq|Frequently asked questions]]
* [[About Board Game Arena|About Board Game Arena]]
** [[About us|About us]]
** [[Club Board Game Arena|Club Board Game Arena]]
** [[Contact us|Contact us]]
=== Detailed help ===
* [[Getting started|Getting started]]
* [[Referral|Referral]]
* [[Browser support|Browser support]]
* [[Moderation and grades|Moderation and grades]]
* [[Game clock|Game clock]]
* [[Rating|Rating]]
* [[Reputation|Reputation]]
* [[Translation guidelines|Translation guidelines]]
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpeightmastersrevenge|8 Master's revenge]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpgearnpiston|Gear & Piston]]
</td>
<td valign="top">
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpneutreeko|Neutreeko]]
</td>
<td valign="top">
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
</td>
<td valign="top">
* [[Gamehelptargi|Targi]]
* [[Gamehelpsechsnimmt|Take 5!]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
</td>
<td valign="top">
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
0ee543bd56e2d6f5fcf33341ae09fa0d34fd91ad
Gamehelpdiams
0
38
1154
153
2014-07-05T09:43:36Z
Magposunnie
5907
/* Goal */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2nd gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2nd round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color than the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty ended...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will lose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
fa8b4f0cb77ad48f727d7bb6ad3437e72e960a8f
1155
1154
2014-07-05T09:45:07Z
Magposunnie
5907
/* Rules summary */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2nd gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2nd round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color as the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty handed...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will lose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
08c4b3313b141e3cf1f4c1569b7b3d3152716a53
1156
1155
2014-07-05T09:46:42Z
Magposunnie
5907
/* Rules summary */
wikitext
text/x-wiki
== Goal ==
Secure as many '''diamond collections''' as you can in your safe!
A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10.
Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10').
Bonus points will be earned at the end of the round :
* for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie)
* and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie).
On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2nd gets 3 chips and so on).
The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2nd round who will get the victory)
== Rules summary ==
On your turn, you must first choose between two 'draw actions' (phase 1):
* Draw one card and put it in your hand
* Draw two cards and put them on the market.
Then you will have to choose between two 'play actions' (phase 2):
* Select one of your cards and go to the market with it. Once on the market, you can:
** Take all cards of the same color as the one you went to the market with (including it)
** Take a selection of cards whose digits sum up to the digit of the card you went to the market with
** Or come back empty-handed...
* Select cards in your hand and secure them into your safe. In order to be valid, your selection:
** Must contain at least one collection (three diamonds of the same color)
** Can contain diamonds matching a collection already present in your safe (in order to expand the collection)
At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5.
== Special cards ==
Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''.
Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows:
'''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will lose yours!)
'''Secur`express''' enables you to secure diamonds of one quality already present in your safe
'''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!)
'''Sleight of hand''' enables you to take any diamond you want from the market, just like that!
== Available variants ==
'''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts!
'''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end!
'''Have a good game!'''
dfb28ed3f68fa98582c08b8b38661b359a57ca53
Gamehelpdudo
0
165
1157
1144
2014-07-05T12:40:10Z
Wolfkin
3936
/* Goal of the Game */ moving to top.. this exception isn't part of the goals of the game
wikitext
text/x-wiki
Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version.
Unfortunately for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version.
==Rules for Perudo (Asmodée version)==
===Goal of the Game===
Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner!
===Set up===
Each player starts with 5 dice which have the following faces:
# Paco
# value 2
# value 3
# value 4
# value 5
# value 6
Based on the amount of players the game begins with the following number of total dice:
<table border="1">
<tr>
<td> Nr. players </td>
<td> Nr. dice </td>
</tr>
<tr>
<td> 2 </td>
<td> 10 </td>
</tr>
<tr>
<td> 3 </td>
<td> 15 </td>
</tr>
<tr>
<td> 4 </td>
<td> 20 </td>
</tr>
<tr>
<td> 5 </td>
<td> 25 </td>
</tr>
<tr>
<td> 6 </td>
<td> 30 </td>
</tr>
</table>
===Round order===
All players roll their dice and check what they rolled.
The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die.
'''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico.
After a bid is placed, the turn is passed on to the player on his left, this player has 2 options:
# If he thinks that the last bid was wrong he can say "Dudo" (i doubt)
# If he thinks the last bid is reasonable, then he must increase the last bid.
====Option 1: calling Dudo====
As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/>
'''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/>
In this case the player who called Dudo was wrong to have doubted and loses one die.<br/>
'''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/>
In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die.
The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game.
====Option 2: increasing the bid====
To increase a bid a player has to choose one of the following options:
# increase the number of dice, thus the value stays the same
# increase the value on the die, thus the number of dice stays the same
Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts.
===Special rules===
The side of the die with the paco on is special
This side counts as a joker for the number of eyes when a Dudo is called.
As example: The bid on which a Dudo was called is: 9 dice with a value of 3.
<table style="width:300px" border="1">
<caption>''These dice are on the table'' </caption>
<tr><td></td><th colspan="6">Die faces</th></tr>
<tr><th>Player</th><th>Paco</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th></tr>
<tr><td>Mike</td><td>1</td><td>2</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>Lucy</td><td>0</td><td>3</td><td>1</td><td>1</td><td>0</td><td>0</td></tr>
<tr><td>John</td><td>3</td><td>0</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>Susan</td><td>1</td><td>0</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
</table>
There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die.
As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up.
Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco.
The Next player can now choose to either
# Increase the number of dice with a paco
# Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra.
Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11)
===Palifico===
The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated).
===Optional rules===
<ol>
<li>'''Calza!'''<br/>
A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza.
If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round.
</li>
<li>'''The lost dice are visible'''<br/>
When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid.
</li></ol>
36fd19ab6020aba475beb36f7ea897f48891a5b0
1158
1157
2014-07-05T13:10:09Z
Wolfkin
3936
table reformatting.
wikitext
text/x-wiki
Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version.
Unfortunately for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version.
''Whenever we use '''he''' it can also be read as '''she''' ''
==Rules for Perudo (Asmodée version)==
===Goal of the Game===
Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner!
===Set up===
Each player starts with 5 dice which have the following faces:
# Paco
# value 2
# value 3
# value 4
# value 5
# value 6
Based on the amount of players the game begins with the following number of total dice:
{| class="wikitable"
|-
! No. Players
! No. Dice
|-
| 2
| 10
|-
| 3
| 15
|-
| 4
| 25
|-
| 5
| 30
|-
| 6
| 35
|}
===Round order===
All players roll their dice and check what they rolled.
The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die.
'''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico.
After a bid is placed, the turn is passed on to the player on his left, this player has 2 options:
# If he thinks that the last bid was wrong he can say "Dudo" (i doubt)
# If he thinks the last bid is reasonable, then he must increase the last bid.
====Option 1: calling Dudo====
As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/>
'''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/>
In this case the player who called Dudo was wrong to have doubted and loses one die.<br/>
'''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/>
In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die.
The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game.
====Option 2: increasing the bid====
To increase a bid a player has to choose one of the following options:
# increase the number of dice, thus the value stays the same
# increase the value on the die, thus the number of dice stays the same
Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts.
===Special rules===
The side of the die with the paco on is special
This side counts as a joker for the number of eyes when a Dudo is called.
As example: The bid on which a Dudo was called is: 9 dice with a value of 3.
{| class="wikitable" style="width: 300px;"
|+These dice are on the table
|-
!
! colspan="6" | Dice Faces
|-
! Player
! Paco
! 2
! 3
! 4
! 5
! 6
|-
| Mike ||1 ||2 ||1 ||0 ||0 ||1
|-
| Lucy ||0 ||3 ||1 ||1 ||0 ||0
|-
| John ||3 ||0 ||1 ||0 ||0 ||1
|-
| Susan ||1 ||0 ||1 ||1 ||1 ||1
|}
There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die.
As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up.
Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco.
The Next player can now choose to either
# Increase the number of dice with a paco
# Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra.
Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11)
===Palifico===
The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated).
===Optional rules===
<ol>
<li>'''Calza!'''<br/>
A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza.
If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round.
</li>
<li>'''The lost dice are visible'''<br/>
When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid.
</li></ol>
30381c5acaa568b63f6ddef100df92d61055bdec
Grade
0
30
1159
1083
2014-07-07T16:27:52Z
Sourisdudesert
1
Undo revision 1083 by [[Special:Contributions/Da man|Da man]] ([[User talk:Da man|talk]])
wikitext
text/x-wiki
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== All grades ==
* '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel).
* '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points.
* '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade.
* '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased.
* '''Archangel''': this is the Board Game Arena administrators' grade.
* '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time.
* '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...)
5953d5338df3e4a588747647198989d0eede4340
1188
1159
2014-10-10T02:36:26Z
Hongsampotion
6162
/* All grades */
wikitext
text/x-wiki
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== All grades ==
* '''필멸자''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel).
* '''천사''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points.
* '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade.
* '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased.
* '''대천사''': this is the Board Game Arena administrators' grade.
* '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time.
* '''악마''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...)
3332d7f96663605ace423efb152989434633fdd6
Gamehelpsobek
0
166
1160
2014-07-08T01:55:28Z
Wolfkin
3936
setting up.
wikitext
text/x-wiki
#Introduction
The construction of the temple dedicated to Sobek is in full swing. A whole economy has set up next to the construction site: there’s a new market, and the feluccas sailing up and down the Nile are constantly bringing goods of all sorts. Competition between merchants is naturally fierce and some are prepared to become corrupt beyond reason in order to amass glory and riches. Mainly the riches, in fact...
You too are part of the local merchants’ guild and are prepared to do whatever it takes to beat your rivals... You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt!
#Game Turn
On your turn, you must choose one (and only one) of the 3 actions. After which, your turn ends and it is now the player on your left’s turn to choose one of the 3 actions, and then the next, etc.
##Take A Card
When you take a card, you must choose one of the four available cards and add it to your hand.
By available, we mean one of the first four starting with the card nearest to the "0" space.
###Corruption
Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other ards comes with a price... corruption!
The corruption rule is simple: all the cards that you skip end up under your corruption tile.
The corruption rule applies regardless of the type of card taken (goods or character).
##Play A Character
Play one (and only one) character. To do this, play it face up on the discard pile (next to the deck) and apply the power shown on its papyrus.
All the character powers are explained in detail on the last page of the rules.
##Play A Set
A set is a group of goods cards of the same type
To play a set, you must place at least 3 goods cards face up in front of you. (You can, of course, play more.)
`A few notes`:
A set can include one or more amulets (joker).
Each character, being associated with a goods type, can therefore be included in a set of that same goods type.
Note, though, that when a character is played as part of a set, its power is ignored!
It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards.
###Event Tokens
As long as at least 1 of the 5 tokens hasn’t yet been played, playing a set immediately triggers an event.
When you play a set, take all the remaining tokens, choose one, and immediately apply its effect. The token is then discarded.
In order to prevent another player from taking advantage of a token, you may choose a token whose effect cannot be applied or which has no effect on you. In that case, you simply discard it.
All the tokens are explained on the last page of the rules.
1a902ef613b406aa59374518b59baa0d740bd812
1161
1160
2014-07-08T01:57:58Z
Wolfkin
3936
formatting
wikitext
text/x-wiki
=Introduction=
The construction of the temple dedicated to Sobek is in full swing. A whole economy has set up next to the construction site: there’s a new market, and the feluccas sailing up and down the Nile are constantly bringing goods of all sorts. Competition between merchants is naturally fierce and some are prepared to become corrupt beyond reason in order to amass glory and riches. Mainly the riches, in fact...
You too are part of the local merchants’ guild and are prepared to do whatever it takes to beat your rivals... You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt!
=Game Turn=
On your turn, you must choose one (and only one) of the 3 actions. After which, your turn ends and it is now the player on your left’s turn to choose one of the 3 actions, and then the next, etc.
==Take A Card==
When you take a card, you must choose one of the four available cards and add it to your hand.
By available, we mean one of the first four starting with the card nearest to the "0" space.
===Corruption===
Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other ards comes with a price... corruption!
The corruption rule is simple: all the cards that you skip end up under your corruption tile.
The corruption rule applies regardless of the type of card taken (goods or character).
==Play A Character==
Play one (and only one) character. To do this, play it face up on the discard pile (next to the deck) and apply the power shown on its papyrus.
All the character powers are explained in detail on the last page of the rules.
==Play A Set==
A set is a group of goods cards of the same type
To play a set, you must place at least 3 goods cards face up in front of you. (You can, of course, play more.)
`A few notes`:
A set can include one or more amulets (joker).
Each character, being associated with a goods type, can therefore be included in a set of that same goods type.
Note, though, that when a character is played as part of a set, its power is ignored!
It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards.
===Event Tokens===
As long as at least 1 of the 5 tokens hasn’t yet been played, playing a set immediately triggers an event.
When you play a set, take all the remaining tokens, choose one, and immediately apply its effect. The token is then discarded.
In order to prevent another player from taking advantage of a token, you may choose a token whose effect cannot be applied or which has no effect on you. In that case, you simply discard it.
All the tokens are explained on the last page of the rules.
ecd81e81bca8ba535e0019c9d5388f22cabb22f5
1184
1161
2014-07-21T14:01:19Z
Drstuey
3099
complete rewrite, removing the text copied from the rules and summarising instead, plus adding more
wikitext
text/x-wiki
==Theme==
Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There’s a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt.
==Game turns and actions==
On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are:
* '''Take a card from the marketplace and add it to your hand'''
: Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile.
* '''Play a character card and apply its power'''
* '''Play a set'''
: A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored.
: It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards.
: When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded.
==Event tokens==
There are 12 event tokens with 5 randomly selected for each round:
* 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol.
* 2 x Flood - Take another turn
* 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile.
* 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set.
* 1 x Embalming - return all the cards from your corruption pile to your hand
* 1 x Deceit - Score the number of cards in your corruption pile
==Character cards==
* 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand.
* 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded.
* 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile.
* 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile.
* 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set.
* 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing.
==End of the round==
The round ends and is scored when the last card is taken from the marketplace.
Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand.
You cannot play character cards; you cannot add to existing sets.
All cards remaining in the players hand are added to their corruption pile.
Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs.
Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols.
== Game end ==
The game ends after 3 rounds. The game can end early if one player gets more than 100 points.
8d6b03e7700445ee6c02d79ec271b107b1ed9c89
1185
1184
2014-07-21T14:16:51Z
Drstuey
3099
add goods cards
wikitext
text/x-wiki
==Theme==
Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There’s a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt.
==Game turns and actions==
On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are:
* '''Take a card from the marketplace and add it to your hand'''
: Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile.
* '''Play a character card and apply its power'''
: See below for powers.
* '''Play a set'''
: A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored.
: It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards.
: When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded.
==Event tokens==
There are 12 event tokens with 5 randomly selected for each round:
* 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol.
* 2 x Flood - Take another turn
* 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile.
* 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set.
* 1 x Embalming - return all the cards from your corruption pile to your hand
* 1 x Deceit - Score the number of cards in your corruption pile
==Character cards==
* 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand.
* 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded.
* 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile.
* 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile.
* 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set.
* 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing.
==Goods cards==
There are 54 goods cards in total:
6 x Ivory
7 x Ebony
7 x Marble
9 x Cattle
10 x Fish
10 x Wheat
5 x Amulet
Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal.
==End of the round==
The round ends and is scored when the last card is taken from the marketplace.
Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand.
You cannot play character cards; you cannot add to existing sets.
All cards remaining in the players hand are added to their corruption pile.
Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs.
Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols.
== Game end ==
The game ends after 3 rounds. The game can end early if one player gets more than 100 points.
873776f4d7f57963268c504993e6a6d219b7a700
1186
1185
2014-07-22T11:37:02Z
Drstuey
3099
/* Goods cards */
wikitext
text/x-wiki
==Theme==
Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There’s a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt.
==Game turns and actions==
On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are:
* '''Take a card from the marketplace and add it to your hand'''
: Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile.
* '''Play a character card and apply its power'''
: See below for powers.
* '''Play a set'''
: A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored.
: It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards.
: When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded.
==Event tokens==
There are 12 event tokens with 5 randomly selected for each round:
* 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol.
* 2 x Flood - Take another turn
* 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile.
* 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set.
* 1 x Embalming - return all the cards from your corruption pile to your hand
* 1 x Deceit - Score the number of cards in your corruption pile
==Character cards==
* 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand.
* 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded.
* 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile.
* 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile.
* 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set.
* 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing.
==Goods cards==
There are 54 goods cards in total:
:6 x Ivory
:7 x Ebony
:7 x Marble
:9 x Cattle
:10 x Fish
:10 x Wheat
:5 x Amulet
Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal.
==End of the round==
The round ends and is scored when the last card is taken from the marketplace.
Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand.
You cannot play character cards; you cannot add to existing sets.
All cards remaining in the players hand are added to their corruption pile.
Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs.
Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols.
== Game end ==
The game ends after 3 rounds. The game can end early if one player gets more than 100 points.
0f4f9d8bee63407b55ed5d3d4a0fc2e9a1d93085
1187
1186
2014-07-22T11:37:50Z
Drstuey
3099
/* Theme */
wikitext
text/x-wiki
==Theme==
Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There's a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt.
==Game turns and actions==
On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are:
* '''Take a card from the marketplace and add it to your hand'''
: Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile.
* '''Play a character card and apply its power'''
: See below for powers.
* '''Play a set'''
: A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored.
: It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards.
: When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded.
==Event tokens==
There are 12 event tokens with 5 randomly selected for each round:
* 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol.
* 2 x Flood - Take another turn
* 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile.
* 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set.
* 1 x Embalming - return all the cards from your corruption pile to your hand
* 1 x Deceit - Score the number of cards in your corruption pile
==Character cards==
* 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand.
* 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded.
* 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile.
* 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile.
* 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set.
* 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing.
==Goods cards==
There are 54 goods cards in total:
:6 x Ivory
:7 x Ebony
:7 x Marble
:9 x Cattle
:10 x Fish
:10 x Wheat
:5 x Amulet
Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal.
==End of the round==
The round ends and is scored when the last card is taken from the marketplace.
Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand.
You cannot play character cards; you cannot add to existing sets.
All cards remaining in the players hand are added to their corruption pile.
Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs.
Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols.
== Game end ==
The game ends after 3 rounds. The game can end early if one player gets more than 100 points.
30e7c1e67b298ba7b4c34925c31df0ad74a8049e
Gamehelphive
0
167
1162
2014-07-09T02:55:38Z
Rainn
5818
Created page with "Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides l..."
wikitext
text/x-wiki
Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times.
The first player's Queen Bee to be surrounded on all sides loses.
Movement rules:
* Queen Bee: Can only move one space
*
c10f3c67e3a8da586533c957f7d0c99c04c2cb71
1163
1162
2014-07-09T03:35:38Z
Rainn
5818
wikitext
text/x-wiki
Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times.
The first player's Queen Bee to be surrounded on all sides loses.
Movement rules:
* Queen Bee: Can only move one space
* Beetle: Only one space, but it can move on top of another insect
* Spider: 3 spaces in a straight line
* Grasshopper: Moves to the next open space in a straight line
* Soldier Ant: It can move unlimited times along borders
This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review
987a1958204c98e11d91a5360659d498357bf740
1164
1163
2014-07-09T03:48:20Z
Rainn
5818
wikitext
text/x-wiki
Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times.
The first player's Queen Bee to be surrounded on all sides loses. You must place your Queen be by your fourth turn.
Movement rules:
* Queen Bee: Can only move one space
* Beetle: Only one space, but it can move on top of another insect
* Spider: 3 spaces in a straight line
* Grasshopper: Moves to the next open space in a straight line
* Soldier Ant: It can move unlimited times along borders
This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review
62d0aeacced1b915f73826e493449e2021632d21
Faq
0
3
1165
1134
2014-07-10T21:41:21Z
Jest phulin
3510
Expanded the answer under "turn-based" play. Also fixed a missing double quote, and a misspelling.
wikitext
text/x-wiki
[[Category:Help]]
== General questions ==
===What is Board Game Arena?===
Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser!
===What do you mean by "real time play"?===
On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world.
===What is "turn based play"?===
This is often referred to as "asynchronous play" on other sites, and is used to differentiate against "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move, you are notified that it is your turn (via email or visiting the site). You then go to your game, take your turn, and the process repeats for another player.
===What do I need to play?===
Your browser ... and that's it!
Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime!
In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]).
===How much does it cost to play on BGA?===
Playing on BGA is free.
You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member.
===What are the games available on BGA?===
Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games.
[http://en.boardgamearena.com/#!gamelist See available games].
===What can I do if I have an issue with the website?===
Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5").
If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it.
===What is the legal status of this website?===
All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game).
Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist.
===I'm a game publisher: why would I like to have my game on Board Game Arena?===
The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon!
As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community.
== Meeting players and starting games ==
===I launched a new table but nobody is joining?===
Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment.
Tip: check the number of online/available players for a game before launching the table.
===I joined a game. When does the game start?===
Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table.
If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table.
===What is the meaning of the small color circle next to players names?===
* http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently.
* http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently.
* http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline.
===What does the '% hits' statistic mean?===
% hits = number of victory points / number of games played
Where number of victory points is the following:
* When you win a 2 players game: 1 point.
* When you win a 3 players game: 1.5 points.
* When you win a 4 players game: 2 points.
* etc.
This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc.
== During the game ==
===What is the meaning of the icons next to players names?===
* http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now.
* http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;)
* http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue.
* http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player.
When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play.
===A player has to make a move but he/she doesn't. What can I do?===
* First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is.
* Then you can ask this player to confirm that he is still thinking about how to play.
* If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily.
* If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game.
===What is the current progression of the game I'm playing?===
A percentage of progression is displayed on the top of the web page.
There is also a progress bar at the bottom of the web page shows you the current progression of the game.
===What is forbidden on Board Game Arena?===
* Leaving a game in progress on purpose.
* Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation.
* Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself.
* Running out of time on the game clock.
* Giving some piece of information about the current game situation that corrupts the normal game flow.
* Communicating with another player about the game privately (ex: with MSN).
* Provocation / triumphalism / defeatism ... anything which is not fair play.
* Having a shocking avatar (no advertisement, no politics, ...)
Going against these rules will affect your reputation.
===What is absolutely forbidden in Board Game Arena?===
* Creating multiple accounts and playing against oneself.
* Insulting other players in any manner.
Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP.
===What if some player does something wrong?===
The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not.
If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game.
If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures.
0fd6cffd7d9330120d8519b19377e164814026d9
Gamehelpcoloretto
0
33
1166
705
2014-07-14T13:40:59Z
Zlatovrana
6098
wikitext
text/x-wiki
There are several colors of chameleons (depending on the number of players) and 2 kinds of special cards: Joker and +2.
At the beginning each players gets randomly 1 card with a chameleon of different color than any other player.
On their turn players can :
1. draw a new card and put it in one of the rows (there are as many rows as players)
2. take a row of cards
When a player takes a row his or her turn is skipped until all players have taken a row. Then a new round starts, and players can again fill rows with cards.
The game ends at the end of a round during which the 'Last round' card is drawn. The player who drew the 'Last round' card puts it away and draws another card.
Same colored chameleons are put into sets. The more cards of that color you have the more points it is worth.
Only 3 sets bring you positive points, while every other set brings you negative points. You get to choose at the end of the game which sets will be positive (the bga does that for you).
The Joker (chameleon with many-colored background) can be put into any set at the end of the game.
+2 always brings you 2 positive points at the end of the game.It is never a part of a set.
The player with the most points wins.
c440cd17b5b5aa9c334194d1f39c5453a42d920d
Gamehelpthroughtheages
0
168
1167
2014-07-18T02:44:41Z
Rainn
5818
Created page with "Turn structure: * Play a political card (if you have one) * Spend your ''military actions'' to build military units, and ''civil actions'' to: ** pick cards from the card rows..."
wikitext
text/x-wiki
Turn structure:
* Play a political card (if you have one)
* Spend your ''military actions'' to build military units, and ''civil actions'' to:
** pick cards from the card rows
** play cards to your tableau
** increase your population
** build/upgrade farms, mines, or urban buildings
Symbols and counters:
* '''yellow''' counters represent your population. They can be in one of three places:
** on your farms, mines, urban buildings, or military units (representing workers)
** your available population
** your "population bank"
444adf5b9707a0e8cf7aa41c63055b3d89137622
1168
1167
2014-07-18T02:53:55Z
Rainn
5818
wikitext
text/x-wiki
Turn structure:
* Play a political card (if you have one)
* Spend your ''military actions'' to build military units, and ''civil actions'' to:
** pick cards from the card rows
** play cards to your tableau
** increase your population
** build/upgrade farms, mines, or urban buildings
Symbols and counters:
* '''yellow''' counters represent your population. They can be in one of three places:
** on your farms, mines, urban buildings, or military units (representing workers)
** on your available population, which are available to place on your cards
** on your "yellow bank" -- when this is empty, you can no longer increase your available population
* '''blue''' counters represent food or resources. They can be in two places:
** on your farms or mines
** on your "blue bank" -- when this is empty, you can no longer produce
* '''white''' circles (on some cards) represent civil actions
* '''red''' circles (on some cards) represent military actions
c1ff953ddca58a8a55a3f4da75c92308a1aa124d
1169
1168
2014-07-18T02:56:30Z
Rainn
5818
wikitext
text/x-wiki
Turn structure:
* Play a political card (if you have one)
* Spend your ''military actions'' to build military units, and ''civil actions'' to:
** pick cards from the card rows (if you have room in your hand)
** play cards to your tableau
** increase your population
** build/upgrade farms, mines, or urban buildings
Yellow counters represent your population. They can be in one of three places:
* on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers)
* on your available population, which are available to place on your cards
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
Blue counters represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce
3ec12510138b87117c4b4710a14712712bfc8b96
1170
1169
2014-07-18T03:04:29Z
Rainn
5818
wikitext
text/x-wiki
Turn structure:
1. Play a political card (if you have one)
2. Spend your ''military actions'' to build military units, and ''civil actions'' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
Yellow counters represent your population. They can be in one of three places:
* on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers)
* on your available population, which are available to place on your cards
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
Blue counters represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce
Building or upgrading farms will help you increase your population.
Building or upgrading mines will help you build more farms, mines, urban buildings, or military.
Producing more ''science'' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military.
When your population grows, you will need to produce more ''happiness'' or your workers will stop working.
Producing ''culture'' will earn you victory points.
Producing more ''military strength'' will protect you from raids or wars.
There are 3 versions:
* ''simple'' plays through Age I
* ''advanced'' plays through Age II, and introduces colonies, raids, unhappiness, and corruption
* ''complete'' plays through Age III, and introduces wars
d57e655edd2555f710f45060b0300fc67ace524f
1171
1170
2014-07-18T03:20:16Z
Rainn
5818
wikitext
text/x-wiki
Turn structure:
1. Play a political card (if you have one)
2. Spend your ''military actions'' to build military units, and ''civil actions'' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
Yellow counters represent your population. They can be in one of three places:
* on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers)
* on your available population, which are available to place on your cards
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
Blue counters represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce
Building up your civilisation:
* Building or upgrading farms will help you increase your population.
* Building or upgrading mines will help you build more farms, mines, urban buildings, or military.
* Producing more ''science'' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military.
* When your population grows, you will need to produce more ''happiness'' or your workers will stop working.
* Producing ''culture'' will earn you victory points.
* Producing more ''military strength'' will protect you from raids or wars.
There are 3 versions of ''Through the Ages'':
* ''simple'' plays through Age I
* ''advanced'' plays through Age II, and introduces colonies, raids, unhappiness, and corruption
* ''complete'' plays through Age III, and introduces wars
157642326b5576dee833967d04fdc9fab0f7ca09
1172
1171
2014-07-18T03:22:22Z
Rainn
5818
wikitext
text/x-wiki
During your turn, you may spend your ''civil actions'' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
* but building/upgrading military units uses your ''military actions''
Yellow counters represent your population. They can be in one of three places:
* on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers)
* on your available population, which are available to place on your cards
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
Blue counters represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce
Building up your civilisation:
* Building or upgrading farms will help you increase your population.
* Building or upgrading mines will help you build more farms, mines, urban buildings, or military.
* Producing more ''science'' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military.
* When your population grows, you will need to produce more ''happiness'' or your workers will stop working.
* Producing ''culture'' will earn you victory points.
* Producing more ''military strength'' will protect you from raids or wars.
There are 3 versions of ''Through the Ages'':
* ''simple'' plays through Age I
* ''advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption
* ''complete'' plays through Age III, and introduces wars
e486e3fac3720372a1217da8821347534e6d0c06
1173
1172
2014-07-18T03:22:56Z
Rainn
5818
wikitext
text/x-wiki
During your turn, you may spend your '''civil actions''' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
* but building/upgrading military units uses your '''military actions'''
'''Yellow counters''' represent your population. They can be in one of three places:
* on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers)
* on your available population, which are available to place on your cards
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
'''Blue counters''' represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce
Building up your civilisation:
* Building or upgrading farms will help you increase your population.
* Building or upgrading mines will help you build more farms, mines, urban buildings, or military.
* Producing more ''science'' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military.
* When your population grows, you will need to produce more ''happiness'' or your workers will stop working.
* Producing ''culture'' will earn you victory points.
* Producing more ''military strength'' will protect you from raids or wars.
There are 3 versions of ''Through the Ages'':
* ''Simple'' plays through Age I
* ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption
* ''Complete'' plays through Age III, and introduces wars
e7a3197b62b75f29713c518279f456e960c7fd15
1174
1173
2014-07-18T03:49:14Z
Rainn
5818
wikitext
text/x-wiki
During your turn, you may spend your '''civil actions''' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
* but building/upgrading military units uses your '''military actions'''
'''Yellow counters''' represent your population. They can be in one of three places:
* on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers)
* on your available population, which are available to place on your cards
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
'''Blue counters''' represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce
Building up your civilisation:
* Building or upgrading farms will help you increase your population.
* Building or upgrading mines will help you build more farms, mines, urban buildings, or military.
* Producing more '''science''' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military.
* When your population grows, you will need to produce more '''happiness''' or your workers will stop working.
* Producing '''culture''' will earn you victory points.
* Producing more '''military strength''' will protect you from raids or wars.
There are 3 versions of ''Through the Ages'':
* ''Simple'' plays through Age I
* ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption
* ''Complete'' plays through Age III, and introduces wars
99edd3832c3b0f626ef487087673979df4d27f2b
1175
1174
2014-07-18T04:04:00Z
Rainn
5818
wikitext
text/x-wiki
During your turn, you may spend your '''civil actions''' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
* but building/upgrading military units uses your '''military actions'''
'''Yellow counters''' represent your population. They can be in one of three places:
* on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers)
* on your available population, which are available to place on your cards
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
'''Blue counters''' represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce
Building up your civilisation:
* '''Food''' lets you move workers from your yellow bank to your available worker pool.
* '''Resources''' let you move workers from your available worker pool to a card on your tableau.
* '''Science'' (light bulbs) lets you move cards from your hand to your tableau.
* When your population grows, you will need to produce more '''happiness''' or your workers will stop working.
* Producing '''culture''' will earn you victory points.
* Producing more '''military strength''' will protect you from raids or wars.
There are 3 versions of ''Through the Ages'':
* ''Simple'' plays through Age I
* ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption
* ''Complete'' plays through Age III, and introduces wars
88888c63ee8358a776fcef0245588af116fe7fd3
1176
1175
2014-07-18T04:04:19Z
Rainn
5818
wikitext
text/x-wiki
During your turn, you may spend your '''civil actions''' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
* but building/upgrading military units uses your '''military actions'''
'''Yellow counters''' represent your population. They can be in one of three places:
* on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers)
* on your available population, which are available to place on your cards
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
'''Blue counters''' represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce
Building up your civilisation:
* '''Food''' lets you move workers from your yellow bank to your available worker pool.
* '''Resources''' let you move workers from your available worker pool to a card on your tableau.
* '''Science''' (light bulbs) lets you move cards from your hand to your tableau.
* When your population grows, you will need to produce more '''happiness''' or your workers will stop working.
* Producing '''culture''' will earn you victory points.
* Producing more '''military strength''' will protect you from raids or wars.
There are 3 versions of ''Through the Ages'':
* ''Simple'' plays through Age I
* ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption
* ''Complete'' plays through Age III, and introduces wars
9b829079a84c97e6facc85dcff01bdeb8d0afe63
1177
1176
2014-07-18T04:05:29Z
Rainn
5818
wikitext
text/x-wiki
During your turn, you may spend your '''civil actions''' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
* but building/upgrading military units uses your '''military actions'''
'''Yellow counters''' represent your population. They can be in one of three places:
* on the cards on your tableau
* on your available worker pool
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
'''Blue counters''' represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce food or resources
Building up your civilisation:
* '''Food''' lets you move workers from your yellow bank to your available worker pool.
* '''Resources''' let you move workers from your available worker pool to a card on your tableau.
* '''Science''' (light bulbs) lets you move cards from your hand to your tableau.
* When your population grows, you will need to produce more '''happiness''' or your workers will stop working.
* Producing '''culture''' will earn you victory points.
* Producing more '''military strength''' will protect you from raids or wars.
There are 3 versions of ''Through the Ages'':
* ''Simple'' plays through Age I
* ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption
* ''Complete'' plays through Age III, and introduces wars
c81481d2450cf4d42b4d79e8a9629461a81e5aea
1178
1177
2014-07-18T04:06:08Z
Rainn
5818
wikitext
text/x-wiki
During your turn, you may spend your '''actions points''' to:
* pick cards from the card rows (if you have room in your hand)
* play cards to your tableau
* increase your population
* build/upgrade farms, mines, or urban buildings
* build/upgrade military units
'''Yellow counters''' represent your population. They can be in one of three places:
* on the cards on your tableau
* on your available worker pool
* on your "yellow bank" -- when this is empty, you can no longer increase your available population
'''Blue counters''' represent food or resources. They can be in two places:
* on your farms or mines
* on your "blue bank" -- when this is empty, you can no longer produce food or resources
Building up your civilisation:
* '''Food''' lets you move workers from your yellow bank to your available worker pool.
* '''Resources''' let you move workers from your available worker pool to a card on your tableau.
* '''Science''' (light bulbs) lets you move cards from your hand to your tableau.
* When your population grows, you will need to produce more '''happiness''' or your workers will stop working.
* Producing '''culture''' will earn you victory points.
* Producing more '''military strength''' will protect you from raids or wars.
There are 3 versions of ''Through the Ages'':
* ''Simple'' plays through Age I
* ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption
* ''Complete'' plays through Age III, and introduces wars
484660cf22ac79264faa9e91bdd7256ebe331837
Gamehelptargi
0
169
1179
2014-07-18T05:23:43Z
Rainn
5818
Created page with "Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column ..."
wikitext
text/x-wiki
Each round of play has the following stages:
# Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi.
# Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi.
# You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau.
167801bdf5386c5abc0261fa03846952fd556bb5
1180
1179
2014-07-18T05:27:16Z
Rainn
5818
wikitext
text/x-wiki
Each round of play has the following stages:
# Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi.
# Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi.
# You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau.
You may only hold 3 gold and 10 goods total between rounds.
6a60c8ce5619e74e6f8336596b4d492c6d355de0
1181
1180
2014-07-18T06:29:50Z
Rainn
5818
wikitext
text/x-wiki
Each round of play has the following stages:
# Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi.
# Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi.
# You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau.
You may only hold 3 gold and 10 goods total between rounds.
In addition to the victory points earned during the game and from special card abilities, you also get:
* 4 victory points for a building a row of identical cards in your tableau, and
* 2 victory points for a row of unique cards
54704b1066c0fbc0e49139892c7cb8efa0c61b01
1182
1181
2014-07-18T06:45:12Z
Rainn
5818
wikitext
text/x-wiki
Each round of play has the following stages:
# Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi.
# Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi.
# You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau.
You may only hold 3 gold and 10 goods total between rounds.
The game ends when a player has filled their tableau, or when the robber has completed one jog around the map.
In addition to the victory points earned during the game and from special card abilities, you also get:
* 4 victory points for a building a row of identical cards in your tableau, and
* 2 victory points for a row of unique cards
154f31063c025aa504be5c1803848d2ab572d886
1183
1182
2014-07-18T06:47:01Z
Rainn
5818
wikitext
text/x-wiki
Each round of play has the following stages:
# Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi.
# Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi.
# You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau.
You may only hold 3 gold and 10 goods total between rounds.
The game ends when a player has filled their tableau, or when the robber has completed one jog around the map.
In addition to the victory points earned during the game and from special card abilities, you also get:
* 4 victory points for a building a row of identical cards in your tableau, and
* 2 victory points for a row of all different cards
b15941ecf92b5d3fb5552e1877d6d7d78db350cf
Translation guidelines
0
18
1189
159
2014-11-02T04:27:29Z
Hongsampotion
6162
/* Who should translate? */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated? ==
Every string of text for the main site interface and for the games' interfaces are 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometime later...
== 누가 번역할 수 있나요?
이것이 중요합니다: 오로지 원어민만이 주어진 문자를 번역할 수 있습니다.
When translating a game, the translator should know the game thoroughly and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country.
As Board Game Arena's team's mother tongue is French, we will take charge of the French translations.
We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
da5089f67e516bbac0ec204b95374982a60ea52c
1190
1189
2014-11-02T04:27:46Z
Hongsampotion
6162
/* What can be translated? */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language!
== What can be translated? ==
Every string of text for the main site interface and for the games' interfaces are 'internationalized' and can be translated.
For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometime later...
== 누가 번역할 수 있나요?
이것이 중요합니다: 오로지 원어민만이 주어진 문자를 번역할 수 있습니다.
When translating a game, the translator should know the game thoroughly and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country.
As Board Game Arena's team's mother tongue is French, we will take charge of the French translations.
We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
b4238e3460156a36fc93ebbe7b983f4c32fdfb05
1192
1190
2015-03-17T00:58:42Z
Aravis
6190
/* What can be translated? */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language!
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요?
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
d0c58d7f55d5800a21c3d5033f1cdbffad24db1a
1193
1192
2015-03-17T00:59:01Z
Aravis
6190
/* 어떤 부분을 번역해도 되나요? */
wikitext
text/x-wiki
The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language!
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
8da95f7ba7cf659cb88d2a939845efb1412e852e
1194
1193
2015-03-17T01:03:51Z
Aravis
6190
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들었습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
3a491441696725a4230ec3714b545ba5f528d97c
1195
1194
2015-03-17T01:04:35Z
Aravis
6190
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들어 졌습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== About context ==
Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them.
Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
51b7623ebb073dadc03031e0a2e6e5255f718aba
1196
1195
2015-03-17T01:10:30Z
Aravis
6190
/* About context */
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들어 졌습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== 맥락을 고려한 번역 ==
어떤 문장이나 문구는 게임 맥락에 따라 다르게 번역해야 합니다. 이러한 경우라면 가장 명확한 방법으로 번역하십시오.
이 경우, 번역한 내용이 게임에 적용된 후 다른 사용자들이 적당하지 않은 번역으로 생각했을 때 이를 정정할 수도 있습니다.
또, 당신이 [http://forum.boardgamearena.com/viewforum.php?f=11 번역 포럼]에 영어나 불어로 이런 맥락을 고려한 번역이 필요한 부분을 알려주시면 그에 따라 정정할 수 있게 하겠습니다.
== When will the site be made available in a new language it is being translated into? ==
As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
3f421300496e876f7455d867d214061a00ca57cb
1197
1196
2015-03-17T01:13:54Z
Aravis
6190
/* When will the site be made available in a new language it is being translated into? */
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들어 졌습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== 맥락을 고려한 번역 ==
어떤 문장이나 문구는 게임 맥락에 따라 다르게 번역해야 합니다. 이러한 경우라면 가장 명확한 방법으로 번역하십시오.
이 경우, 번역한 내용이 게임에 적용된 후 다른 사용자들이 적당하지 않은 번역으로 생각했을 때 이를 정정할 수도 있습니다.
또, 당신이 [http://forum.boardgamearena.com/viewforum.php?f=11 번역 포럼]에 영어나 불어로 이런 맥락을 고려한 번역이 필요한 부분을 알려주시면 그에 따라 정정할 수 있게 하겠습니다.
== 번역한 내용은 언제 적용되나요? ==
어떤 언어에 대해 새로 번역을 하게 되면 충분한 분량이 생성되었다고 BGA 팀이 판단했을 때 사이트에 실제 번역내용이 적용되어 나타나게 됩니다.
== I fixed some translations, but they don't appear to have changed on the site ==
Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
c9ee960000ff2389286f2f8a98fcb2b8fca2aed5
1198
1197
2015-03-17T01:15:23Z
Aravis
6190
/* I fixed some translations, but they don't appear to have changed on the site */
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들어 졌습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== 맥락을 고려한 번역 ==
어떤 문장이나 문구는 게임 맥락에 따라 다르게 번역해야 합니다. 이러한 경우라면 가장 명확한 방법으로 번역하십시오.
이 경우, 번역한 내용이 게임에 적용된 후 다른 사용자들이 적당하지 않은 번역으로 생각했을 때 이를 정정할 수도 있습니다.
또, 당신이 [http://forum.boardgamearena.com/viewforum.php?f=11 번역 포럼]에 영어나 불어로 이런 맥락을 고려한 번역이 필요한 부분을 알려주시면 그에 따라 정정할 수 있게 하겠습니다.
== 번역한 내용은 언제 적용되나요? ==
어떤 언어에 대해 새로 번역을 하게 되면 충분한 분량이 생성되었다고 BGA 팀이 판단했을 때 사이트에 실제 번역내용이 적용되어 나타나게 됩니다.
== 번역한 내용을 수정했는데, 바로 적용이 되지 않습니다. ==
번역에 관한 데이터베이스는 수시로 업데이트 됩니다. 그렇게 때문에 수정 내용이 적용될 때까지 하룻밤 정도가 소요됩니다.
== How long will it be possible to change the translations? ==
The first translations may not be perfect (as explained in the 'about context' section).
So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
43f0d099b6f91a640bcd81fd578877748bbe16f6
1199
1198
2015-03-17T01:19:06Z
Aravis
6190
/* How long will it be possible to change the translations? */
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들어 졌습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== 맥락을 고려한 번역 ==
어떤 문장이나 문구는 게임 맥락에 따라 다르게 번역해야 합니다. 이러한 경우라면 가장 명확한 방법으로 번역하십시오.
이 경우, 번역한 내용이 게임에 적용된 후 다른 사용자들이 적당하지 않은 번역으로 생각했을 때 이를 정정할 수도 있습니다.
또, 당신이 [http://forum.boardgamearena.com/viewforum.php?f=11 번역 포럼]에 영어나 불어로 이런 맥락을 고려한 번역이 필요한 부분을 알려주시면 그에 따라 정정할 수 있게 하겠습니다.
== 번역한 내용은 언제 적용되나요? ==
어떤 언어에 대해 새로 번역을 하게 되면 충분한 분량이 생성되었다고 BGA 팀이 판단했을 때 사이트에 실제 번역내용이 적용되어 나타나게 됩니다.
== 번역한 내용을 수정했는데, 바로 적용이 되지 않습니다. ==
번역에 관한 데이터베이스는 수시로 업데이트 됩니다. 그렇게 때문에 수정 내용이 적용될 때까지 하룻밤 정도가 소요됩니다.
== 번역에 대한 수정은 얼마 동안 가능한가요? ==
처음 번역 결과물이 나오면 완전하지 않을 경우가 많습니다. 그렇기 때문에 각 번역 문구들이 '확정'되기 전까지 고칠 수 있습니다.
하지만 30일 동안 번역물에 대한 수정이 더 이상 없어서 번역 결과가 안정화되었다고 생각되면, 황금 아이콘을 붙여 확정된 번역 문구임을 알려줍니다. 이렇게 된 문구는 더 이상 수정할 수 없습니다.
== Is there some reward for translating? ==
Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated).
This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all!
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
5a855796ed626f527195161f8b179de243f9af60
1200
1199
2015-03-17T01:35:10Z
Aravis
6190
/* Is there some reward for translating? */
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들어 졌습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== 맥락을 고려한 번역 ==
어떤 문장이나 문구는 게임 맥락에 따라 다르게 번역해야 합니다. 이러한 경우라면 가장 명확한 방법으로 번역하십시오.
이 경우, 번역한 내용이 게임에 적용된 후 다른 사용자들이 적당하지 않은 번역으로 생각했을 때 이를 정정할 수도 있습니다.
또, 당신이 [http://forum.boardgamearena.com/viewforum.php?f=11 번역 포럼]에 영어나 불어로 이런 맥락을 고려한 번역이 필요한 부분을 알려주시면 그에 따라 정정할 수 있게 하겠습니다.
== 번역한 내용은 언제 적용되나요? ==
어떤 언어에 대해 새로 번역을 하게 되면 충분한 분량이 생성되었다고 BGA 팀이 판단했을 때 사이트에 실제 번역내용이 적용되어 나타나게 됩니다.
== 번역한 내용을 수정했는데, 바로 적용이 되지 않습니다. ==
번역에 관한 데이터베이스는 수시로 업데이트 됩니다. 그렇게 때문에 수정 내용이 적용될 때까지 하룻밤 정도가 소요됩니다.
== 번역에 대한 수정은 얼마 동안 가능한가요? ==
처음 번역 결과물이 나오면 완전하지 않을 경우가 많습니다. 그렇기 때문에 각 번역 문구들이 '확정'되기 전까지 고칠 수 있습니다.
하지만 30일 동안 번역물에 대한 수정이 더 이상 없어서 번역 결과가 안정화되었다고 생각되면, 황금 아이콘을 붙여 확정된 번역 문구임을 알려줍니다. 이렇게 된 문구는 더 이상 수정할 수 없습니다.
== 번역에 따른 보상이 있나요? ==
물론입니다! 번역자가 번역 결과물에 대해 100 개의 확정 아이콘을 받을 때마다 1개월의 무료 '보드 게임 아레나 클럽' 회원 자격을 얻습니다. 이는 BGA를 더 많은 사람이 이용할 수 있도록 도와주신 것에 대한 상징적인 보상입니다. 이렇게 해서 다양한 나라의 사람들과 보드 게임을 즐길 수 있다면 모두에게도 큰 보상일 것입이니다.
== Translation tips ==
* Use the 'TAB' key to go from one text box to another. This is easier than clicking.
* Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}).
* When in doubt, leave a comment for the next translator.
* When you fix someone's translation, leave a comment if the reason for the change is not obvious.
* When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing.
b3a7d7f188bdfcd22fa620068040ff4019a840b1
1201
1200
2015-03-17T01:40:50Z
Aravis
6190
/* Translation tips */
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들어 졌습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== 맥락을 고려한 번역 ==
어떤 문장이나 문구는 게임 맥락에 따라 다르게 번역해야 합니다. 이러한 경우라면 가장 명확한 방법으로 번역하십시오.
이 경우, 번역한 내용이 게임에 적용된 후 다른 사용자들이 적당하지 않은 번역으로 생각했을 때 이를 정정할 수도 있습니다.
또, 당신이 [http://forum.boardgamearena.com/viewforum.php?f=11 번역 포럼]에 영어나 불어로 이런 맥락을 고려한 번역이 필요한 부분을 알려주시면 그에 따라 정정할 수 있게 하겠습니다.
== 번역한 내용은 언제 적용되나요? ==
어떤 언어에 대해 새로 번역을 하게 되면 충분한 분량이 생성되었다고 BGA 팀이 판단했을 때 사이트에 실제 번역내용이 적용되어 나타나게 됩니다.
== 번역한 내용을 수정했는데, 바로 적용이 되지 않습니다. ==
번역에 관한 데이터베이스는 수시로 업데이트 됩니다. 그렇게 때문에 수정 내용이 적용될 때까지 하룻밤 정도가 소요됩니다.
== 번역에 대한 수정은 얼마 동안 가능한가요? ==
처음 번역 결과물이 나오면 완전하지 않을 경우가 많습니다. 그렇기 때문에 각 번역 문구들이 '확정'되기 전까지 고칠 수 있습니다.
하지만 30일 동안 번역물에 대한 수정이 더 이상 없어서 번역 결과가 안정화되었다고 생각되면, 황금 아이콘을 붙여 확정된 번역 문구임을 알려줍니다. 이렇게 된 문구는 더 이상 수정할 수 없습니다.
== 번역에 따른 보상이 있나요? ==
물론입니다! 번역자가 번역 결과물에 대해 100 개의 확정 아이콘을 받을 때마다 1개월의 무료 '보드 게임 아레나 클럽' 회원 자격을 얻습니다. 이는 BGA를 더 많은 사람이 이용할 수 있도록 도와주신 것에 대한 상징적인 보상입니다. 이렇게 해서 다양한 나라의 사람들과 보드 게임을 즐길 수 있다면 모두에게도 큰 보상일 것입이니다.
== 번역 사이트 이용 도움말 ==
* '탭' 키를 누르면 다음 글상자로 이동합니다. 마우스로 다음 상자를 누르는 것보다 훨씬 편합니다.
* ${SOMETHING}, %SOMETHING, <SOMETHING>와 같이 표시된 예약어는 번역 결과에도 그대로 있어야 합니다. 각 언어의 특성에 따라 예약어의 위치를 조정할 수 있습니다.
* 번역이 적당하지 않다고 생각할 때는 다른 사람이 번역에 참고할 수 있도록 코멘트 창에 글을 남기십시오.
* 다른 사람이 이미 번역한 내용을 고치고자 할 때, 특별히 새로 번역한 내용 또한 명백하지 않을 때는, 코멘트를 남기십시오.
* 번역이 맥락에 정확히 맞지 않다고 생각되면, 다른 사용자가 그에 대해 수정을 할 수 있도록 직역을 해두십시오.
47f4d415d64b59d0705ec00e0e4fef55043f5db9
Gamehelpquantum
0
170
1191
2015-03-10T05:10:40Z
Aravis
6190
새 문서: == 함정의 주특기 소개 == 함정은 각 종류에 따라 정해진 주특기가 있으며, 각 함정은 해당 주특기를 매 턴에 한 번 발동할 수 있습니다. 이...
wikitext
text/x-wiki
== 함정의 주특기 소개 ==
함정은 각 종류에 따라 정해진 주특기가 있으며, 각 함정은 해당 주특기를 매 턴에 한 번 발동할 수 있습니다.
이 때 그 함정은 함정 등급이 바뀌어도 (다시 말해 주사위 숫자가 바뀌어도) 주특기는 단 한 번 발동할 수 있습니다.
주특기 발동은 추가로 액션을 소모하지 않습니다. (그렇지만 대각선 기동 능력이나 수송 능력은 이동 명령 중에 발동되는 것이기에 결과적으로 액션 소모가 있습니다.)
주특기는 자신의 차례에만, 지도 상에 배치되어 함정에 대해서 발동할 수 있습니다. (조선소에 있거나 예비로 있는 함정은 주특기를 발동시킬 수 없습니다.)
함정이 이동명령을 수행하는 도중에는 주특기를 변경할 수 없습니다. 예를 들면 전투를 하기 바로 직전과 같은 경우 주특기를 변경할 수 없습니다.
'''1 (전투함) 타격:''' 전투함에 바로 붙어 있는 상대 함정을 공격
타격 명령은 1칸을 액션 소모 없이 이동/공격할 수 있는 전투함의 주특기이며, 반드시 이동하고자 하는 장소에 상대방이 있어야 합니다. 한 턴에서 액션을 소모하는 일반적인 공격을 전투함이 마친 후에도 주특기를 이용하여 다시 공격하는 것도 가능합니다.
'''2 (기함) 수송:''' 다른 함정을 태워서 이동
기함 주변 (가로, 세로 또는 대각선으로 한 칸)에 있는 함정을 기함 위에 올린 후, 기함이 1칸 또는 2칸 이동할 수 있습니다. 이동을 마치면 함께 수송된 함정을 기함 주변의 빈 공간에 내려놓을 수 있습니다. 기함이 다른 함정을 수송하는 동안은 공격을 수행할 수 없습니다. 하지만 수송된 함정이 아직 이동/공격 명령을 수행하지 않았다면 이동이나 공격 명령을 평소와 다를 바 없이 수행할 수 있습니다.
'''3 (구축함) 공간 이동:''' 지도 상의 다른 함정과 위치 바꾸기
구축함이 공간 이동 주특기를 발동하여도 액션을 소모한 것이 아니므로, 공간 이동 후에라도 이동/공격 명령을 수행할 수 있습니다.
'''4 (호위함) 등급 조정:''' 3등급이나 5등급으로 등급을 조정
등급을 조정하고 나서 새로 바뀐 등급의 주특기를 바로 다시 발동할 수 없습니다. 등급 조정이 이 함정의 주특기였고, 이미 발동되었기 때문입니다.
'''5 (요격기) 대각기동:''' 대각선으로 이동
이동 명령을 내리는 중 대각기동 주특기를 발동시키면 가로, 세로 뿐만 아니라 대각선으로도 이동할 수 있습니다. 가로, 세로, 대각선을 섞어서 이동할 수 있으며, 대각선으로 공격도 가능합니다.
'''6 (정찰기) 주특기 재배정:''' 주사위를 굴려 다른 등급으로 변경
주사위를 굴렸을 때 6이 나오면, 6이 아닌 숫자가 나올 때까지 계속 굴립니다.
41e7b3b752c8712292e2635c54a82a65d7ac7fe3
Translation guidelines
0
18
1202
1201
2015-03-17T04:41:58Z
Aravis
6190
/* 맥락을 고려한 번역 */
wikitext
text/x-wiki
[http://en.boardgamearena.com/#!translationhq 공동 번역 시스템]은 BGA의 모든 것을 여러 언어로 번역하여, 영어나 프랑스어를 모르는 사람들도 보드 게임을 알고, 즐기도록 하려고 만들어 졌습니다. 예를 들자면, 영어를 모르는 10살 짜리 조카랑 '드래곤 하트'를 하려해도 문제 없습니다. BGA에 있는 게임들을 여러분의 언어로 번역해 주시면 됩니다.
== 어떤 부분을 번역해도 되나요? ==
메인 사이트나 게임에서 사용되는 모든 글들은 '다국어 지원' 기능을 갖고 있어서 모두 번역할 수 있습니다.
하지만 포럼의 글이나 웹사이트의 게시물은 현재로선 번역문을 추가할 수 없습니다. 언젠가는 가능할지도 모르겠습니다.
== 누가 번역할 수 있나요? ==
이것이 중요합니다: 오로지 대상 언어를 모국어로 사용하는 사람만이 번역에 참여할 수 있습니다.
게임을 번역할 때, 번역자는 해당 게임을 숙지하고 있어야 하고 가능하다면 실물 게임과 비교할 수 있는 실제 게임과 대상 언어로 된 메뉴얼을 가지고 있어야 합니다. 또한 각 국의 보드게임 이용자들이 쓰고 있는 공식적이거나 자주 쓰는 게임 규칙과 표현을 고려해서 번역하여야 합니다.
== 맥락을 고려한 번역을 해야합니다. ==
어떤 문장이나 문구는 게임 맥락에 따라 다르게 번역해야 합니다. 이러한 경우라면 가장 명확한 방법으로 번역하십시오.
이 경우, 번역한 내용이 게임에 적용된 후 다른 사용자들이 적당하지 않은 번역으로 생각했을 때 이를 정정할 수도 있습니다.
또, 당신이 [http://forum.boardgamearena.com/viewforum.php?f=11 번역 포럼]에 영어나 불어로 이런 맥락을 고려한 번역이 필요한 부분을 알려주시면 그에 따라 정정할 수 있게 하겠습니다.
== 번역한 내용은 언제 적용되나요? ==
어떤 언어에 대해 새로 번역을 하게 되면 충분한 분량이 생성되었다고 BGA 팀이 판단했을 때 사이트에 실제 번역내용이 적용되어 나타나게 됩니다.
== 번역한 내용을 수정했는데, 바로 적용이 되지 않습니다. ==
번역에 관한 데이터베이스는 수시로 업데이트 됩니다. 그렇게 때문에 수정 내용이 적용될 때까지 하룻밤 정도가 소요됩니다.
== 번역에 대한 수정은 얼마 동안 가능한가요? ==
처음 번역 결과물이 나오면 완전하지 않을 경우가 많습니다. 그렇기 때문에 각 번역 문구들이 '확정'되기 전까지 고칠 수 있습니다.
하지만 30일 동안 번역물에 대한 수정이 더 이상 없어서 번역 결과가 안정화되었다고 생각되면, 황금 아이콘을 붙여 확정된 번역 문구임을 알려줍니다. 이렇게 된 문구는 더 이상 수정할 수 없습니다.
== 번역에 따른 보상이 있나요? ==
물론입니다! 번역자가 번역 결과물에 대해 100 개의 확정 아이콘을 받을 때마다 1개월의 무료 '보드 게임 아레나 클럽' 회원 자격을 얻습니다. 이는 BGA를 더 많은 사람이 이용할 수 있도록 도와주신 것에 대한 상징적인 보상입니다. 이렇게 해서 다양한 나라의 사람들과 보드 게임을 즐길 수 있다면 모두에게도 큰 보상일 것입이니다.
== 번역 사이트 이용 도움말 ==
* '탭' 키를 누르면 다음 글상자로 이동합니다. 마우스로 다음 상자를 누르는 것보다 훨씬 편합니다.
* ${SOMETHING}, %SOMETHING, <SOMETHING>와 같이 표시된 예약어는 번역 결과에도 그대로 있어야 합니다. 각 언어의 특성에 따라 예약어의 위치를 조정할 수 있습니다.
* 번역이 적당하지 않다고 생각할 때는 다른 사람이 번역에 참고할 수 있도록 코멘트 창에 글을 남기십시오.
* 다른 사람이 이미 번역한 내용을 고치고자 할 때, 특별히 새로 번역한 내용 또한 명백하지 않을 때는, 코멘트를 남기십시오.
* 번역이 맥락에 정확히 맞지 않다고 생각되면, 다른 사용자가 그에 대해 수정을 할 수 있도록 직역을 해두십시오.
c2fcfdaf0669d8412e5577f10d351840ce491a39
Grade
0
30
1203
1188
2015-03-23T07:04:37Z
Aravis
6190
/* All grades */
wikitext
text/x-wiki
Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players.
When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat).
After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon.
If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub.
== 등급 안내 ==
* '''인간''': Board Game Arena에 처음 가입했을 대의 등급. 전체 대화창에 글을 쓰는 것을 제외한 BGA 웹사이트의 거의 대부분의 기능을 이용할 수 있습니다.
* '''천사''': 일반 사용자 등급. 가입 후 3 일이 지나고 3 경기 이상을 끝내고 평판 점수가 3 점 이상일 때 이 등급이 됩니다.
* '''스랍''': 일반 감독자 등급. BGA의 규칙을 위반하는 사용자들에 대해 벌점을 줄 수 있습니다.
* '''그룹''': 중간 감독자 등급. 일반 관리자들이 공정하게 관리하는 지를 감독합니다.
* '''대천사''': BGA 관리자 등급.
* '''악인''': 규정 위반에 따라 정해진 기간 동안 BGA에서 글을 쓸 수 없는 등급.
* '''악마''': 심각한 규정 위반에 따라 정해진 기간 (또는 영원히) BGA에서의 어떤 활동도 허용되지 않는 등급.
984713ccba9395923e6f73219c24c5743f99977a
1204
1203
2015-03-23T07:11:07Z
Aravis
6190
wikitext
text/x-wiki
Board Game Arena는 사용자끼리 서로 존중하는 커뮤니티입니다. BGA의 등급과 감독 체계는 BGA의 정신을 존중하지 않는 일부 사용자들이 다른 사용자들을 불편하게 하지 않도록 하기 위해 만들어졌습니다.
BGA에 가입하면 '인간' 등급이 되고, 전체 대화창에 글을 쓰는 것과 같은 일부 기능을 제외하면 거의 대부분의 기능을 사용할 수 있습니다.
가입 후 얼마 지나지 않아 '천사' 등급이 될 수 있고, 이 등급이 되면 BGA의 모든 기능을 사용할 수 있습니다. 하지만 BGA의 규칙을 어기게 되면, '악인'이나 '악마' 등급으로 떨어질 수 있습니다.
또한 평판이 좋은 사용자의 경우에는 '스랍' 이나 '그룹' 같은 감독자 등급이 될 수도 있습니다.
== 등급 안내 ==
* '''인간''': Board Game Arena에 처음 가입했을 대의 등급. 전체 대화창에 글을 쓰는 것을 제외한 BGA 웹사이트의 거의 대부분의 기능을 이용할 수 있습니다.
* '''천사''': 일반 사용자 등급. 가입 후 3 일이 지나고 3 경기 이상을 끝내고 평판 점수가 3 점 이상일 때 이 등급이 됩니다.
* '''스랍''': 일반 감독자 등급. BGA의 규칙을 위반하는 사용자들에 대해 벌점을 줄 수 있습니다.
* '''그룹''': 중간 감독자 등급. 일반 관리자들이 공정하게 관리하는 지를 감독합니다.
* '''대천사''': BGA 관리자 등급.
* '''악인''': 규정 위반에 따라 정해진 기간 동안 BGA에서 글을 쓸 수 없는 등급.
* '''악마''': 심각한 규정 위반에 따라 정해진 기간 (또는 영원히) BGA에서의 어떤 활동도 허용되지 않는 등급.
2d3f272fdb222db32ce95aec6baf6e2696f486f5
1218
1204
2016-10-16T02:10:47Z
Recoding
6339
/* 등급 안내 */
wikitext
text/x-wiki
Board Game Arena는 사용자끼리 서로 존중하는 커뮤니티입니다. BGA의 등급과 감독 체계는 BGA의 정신을 존중하지 않는 일부 사용자들이 다른 사용자들을 불편하게 하지 않도록 하기 위해 만들어졌습니다.
BGA에 가입하면 '인간' 등급이 되고, 전체 대화창에 글을 쓰는 것과 같은 일부 기능을 제외하면 거의 대부분의 기능을 사용할 수 있습니다.
가입 후 얼마 지나지 않아 '천사' 등급이 될 수 있고, 이 등급이 되면 BGA의 모든 기능을 사용할 수 있습니다. 하지만 BGA의 규칙을 어기게 되면, '악인'이나 '악마' 등급으로 떨어질 수 있습니다.
또한 평판이 좋은 사용자의 경우에는 '스랍' 이나 '그룹' 같은 감독자 등급이 될 수도 있습니다.
== 등급 안내 ==
* '''인간''': Board Game Arena에 처음 가입했을 때의 등급. 전체 대화창에 글을 쓰는 것을 제외한 BGA 웹사이트의 거의 대부분의 기능을 이용할 수 있습니다.
* '''천사''': 일반 사용자 등급. 가입 후 3 일이 지나고 3 경기 이상을 끝내고 평판 점수가 3 점 이상일 때 이 등급이 됩니다.
* '''스랍''': 일반 감독자 등급. BGA의 규칙을 위반하는 사용자들에 대해 벌점을 줄 수 있습니다.
* '''그룹''': 중간 감독자 등급. 일반 관리자들이 공정하게 관리하는 지를 감독합니다.
* '''대천사''': BGA 관리자 등급.
* '''악인''': 규정 위반에 따라 정해진 기간 동안 BGA에서 글을 쓸 수 없는 등급.
* '''악마''': 심각한 규정 위반에 따라 정해진 기간 (또는 영원히) BGA에서의 어떤 활동도 허용되지 않는 등급.
d9aba88cb00cfc7ff053e2728dd36ecc47a3681f
Gamehelpsechsnimmt
0
171
1205
2015-11-29T02:07:19Z
Jeonghan kim
6251
잭스님트 규칙
wikitext
text/x-wiki
'''잭스님트!'''
이 게임의 기본적인 목표는 카드를 가져가지 않고, 다른 플레이어로 하여금 갖고 가게 하는 것입니다. 모든 플레이어는 66포인트에서 시작합니다. 여기서 카드 위에 그려진 소머리 하나 당 1점씩 감점됩니다. 만일 모든 점수를 잃는 플레이어가 나오게 된다면, 해당 라운드에서 게임은 끝나게 되고, 가장 많은 포인트가 남은 사람이 승리하게 됩니다.
'''게임방법'''
모든 플레이어는 10장의 카드를 갖고 시작합니다. 네 장의 카드는 테이블에 4열로 놓여집니다. 모든 플레이어는 각자 보이지 않게 카드를 한 장 고릅니다. 그리고 모두 골랐다면, 동시에 공개합니다. 카드가 공개되었다면, 카드가 놓이기 시작합니다. 가장 낮은 숫자부터 놓이기 시작합니다. 놓이는 규칙은 다음과 같습니다.
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
게임을 진행할수록, 각 열은 카드로 채워질 것입니다. 5장이 해당 열의 최대 갯수입니다. 만약 누군가가 해당 열의 여섯 장 째의 카드를 놓았다면, 그 열의 카드를 모두 벌점으로 가져가게 됩니다. 이때, 카드 위의 소머리 숫자만큼 포인트가 차감됩니다. 해당 플레이어가 놓았던 마지막 카드(여섯번 째 카드)가 해당 열의 첫 숫자로 진행됩니다.
만약 누군가가 모든 숫자들보다 낮은 숫자를 놓았다면, 한 열을 선택하고 벌점으로 가져간 후, 자신이 놓을 카드를 그 열의 시작하는 카드로 놓습니다.
'''소머리'''
각 카드는 소머리가 있습니다. 이것은 해당 카드의 벌점을 나타냅니다.
5로 끝나는 카드는 벌점 2점, 0으로 끝나는 카드는 벌점 3점, 11의 배수는 벌점 5점, 55는 벌점 7점이며, 나머지는 모두 벌점 1점입니다.
'''라운드 끝내기'''
일단 라운드가 끝나면, 아무도 0점 이하로 떨어지지 않았다면, 새로운 라운드로 넘어갑니다. 만약 누군가가 모든 포인트를 잃었다면, 그 즉시 게임이 끝나고 가장 많은 포인트가 남은 사람이 이깁니다.
'''대체 규칙'''
Tactics: This ruleset changes the number of cards in play based on how many people are playing - other than that the rules are the same. The number of cards is equal to the number of players plus 4, so every card that could be played will find its way onto the table at some point. This changes strategy some and makes paying attention to which cards are have yet to be played important.
Logic: The same as Tactics, except that at the start of the round all of the cards are placed on the table face up, and players take turns choosing cards one at a time to build their hands before the round proper starts.
c433da9d779a91538dc2d45c78c0af442c055e3f
1222
1205
2016-12-10T14:34:48Z
Yooyou7
6164
wikitext
text/x-wiki
'''젝스님트!'''
이 게임의 기본적인 목표는 카드를 가져가지 않고, 다른 플레이어로 하여금 갖고 가게 하는 것입니다. 모든 플레이어는 66포인트에서 시작합니다. 여기서 카드 위에 그려진 소머리 하나 당 1점씩 감점됩니다. 만일 모든 점수를 잃는 플레이어가 나오게 된다면, 해당 라운드에서 게임은 끝나게 되고, 가장 많은 포인트가 남은 사람이 승리하게 됩니다.
'''게임방법'''
모든 플레이어는 10장의 카드를 갖고 시작합니다. 라운드 시작 시 네 장의 카드는 테이블에 4열로 놓여집니다. 모든 플레이어는 각자 보이지 않게 카드를 한 장 고릅니다. 그리고 모두 골랐다면, 동시에 공개합니다. 카드가 공개되었다면, 카드가 놓이기 시작합니다. 가장 낮은 숫자부터 놓이기 시작합니다. 놓이는 규칙은 (Normal 기준으로) 다음과 같습니다. ('''카드 놓기'''를 참조하세요.)
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드는 왼쪽부터 순서대로 놓아진다. 즉, 그 줄의 카드보다 작은 수의 카드는 놓이지 않는다.
게임을 진행할수록, 각 열은 카드로 채워질 것입니다. 5장이 해당 열의 최대 갯수입니다. 만약 누군가가 해당 열의 여섯번째의 카드를 놓았다면, 그 열의 카드를 모두 벌점으로 가져가게 됩니다. 이때, 카드 위의 소머리 숫자만큼 포인트가 차감됩니다. 해당 플레이어가 놓았던 마지막 카드(여섯번 째 카드)가 해당 열의 첫 숫자로 진행됩니다.
만약 누군가가 모든 숫자들보다 낮은 숫자를 놓았다면 (즉, 카드를 놓을 수 있는 열이 없는 경우), 한 열을 선택하고 벌점으로 가져간 후, 자신이 놓을 카드를 그 열의 시작하는 카드로 놓습니다.
'''소머리'''
각 카드는 소머리가 있습니다. 이것은 해당 카드의 벌점을 나타냅니다.
5로 끝나는 카드는 벌점 2점, 0으로 끝나는 카드는 벌점 3점, 11의 배수는 벌점 5점, 55는 벌점 7점이며, 나머지는 모두 벌점 1점입니다.
'''라운드 끝내기'''
일단 라운드가 끝나면, 아무도 0점 이하로 떨어지지 않았다면, 새로운 라운드로 넘어갑니다. 만약 누군가가 모든 포인트를 잃었다면, 그 즉시 게임이 끝나고 가장 많은 포인트가 남은 사람이 이깁니다.
'''변경 가능 규칙'''
- '''카드 세트'''
Normal : 무조건 1~104까지의 카드를 사용합니다. 이에 따라 사용되지 않는 카드는 공개되지 않습니다.
Tactics : 플레이어 수에 따라 사용하는 카드의 수가 바뀝니다. 사용되지 않는 카드가 없도록 카드 수가 조정되며, 이에 따라 숫자의 범위는 1~(인원수*10+4)가 됩니다. 이 방식은 Normal에 비해 다른 전략과 카드 카운팅의 중요성이 커집니다.
Logic: Tactics와 동일하게 카드 장수를 조절하나, 카드 배분을 랜덤이 아닌 1장씩 가져가면서 덱을 만듭니다. 플레이 시간은 길어질 것이나, 운의 요소를 거의 배제할 수 있다는 점이 특이점입니다.
- '''카드 놓기'''
Normal : 게임 방법에 적힌 그대로, 아래와 같이 진행합니다 :
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드는 왼쪽부터 순서대로 놓아진다. 즉, 그 줄의 카드보다 작은 수의 카드는 놓이지 않는다.
Professional : 게임 방법과 다르게, 아래와 같이 진행합니다 :
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드의 방향은 제한이 없다. 즉, 편차가 더 작다면 줄의 맨 왼쪽에 놓아질수도 있다.
c0c1663d890effaec315e3b74d49b60e7a9c523d
1223
1222
2016-12-10T14:35:01Z
Yooyou7
6164
wikitext
text/x-wiki
'''젝스님트!'''
이 게임의 기본적인 목표는 카드를 가져가지 않고, 다른 플레이어로 하여금 갖고 가게 하는 것입니다. 모든 플레이어는 66포인트에서 시작합니다. 여기서 카드 위에 그려진 소머리 하나 당 1점씩 감점됩니다. 만일 모든 점수를 잃는 플레이어가 나오게 된다면, 해당 라운드에서 게임은 끝나게 되고, 가장 많은 포인트가 남은 사람이 승리하게 됩니다.
'''게임방법'''
모든 플레이어는 10장의 카드를 갖고 시작합니다. 라운드 시작 시 네 장의 카드는 테이블에 4열로 놓여집니다. 모든 플레이어는 각자 보이지 않게 카드를 한 장 고릅니다. 그리고 모두 골랐다면, 동시에 공개합니다. 카드가 공개되었다면, 카드가 놓이기 시작합니다. 가장 낮은 숫자부터 놓이기 시작합니다. 놓이는 규칙은 (Normal 기준으로) 다음과 같습니다. ('''카드 놓기'''를 참조하세요.)
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드는 왼쪽부터 순서대로 놓아진다. 즉, 그 줄의 카드보다 작은 수의 카드는 놓이지 않는다.
게임을 진행할수록, 각 열은 카드로 채워질 것입니다. 5장이 해당 열의 최대 갯수입니다. 만약 누군가가 해당 열의 여섯번째의 카드를 놓았다면, 그 열의 카드를 모두 벌점으로 가져가게 됩니다. 이때, 카드 위의 소머리 숫자만큼 포인트가 차감됩니다. 해당 플레이어가 놓았던 마지막 카드(여섯번 째 카드)가 해당 열의 첫 숫자로 진행됩니다.
만약 누군가가 모든 숫자들보다 낮은 숫자를 놓았다면 (즉, 카드를 놓을 수 있는 열이 없는 경우), 한 열을 선택하고 벌점으로 가져간 후, 자신이 놓을 카드를 그 열의 시작하는 카드로 놓습니다.
'''소머리'''
각 카드는 소머리가 있습니다. 이것은 해당 카드의 벌점을 나타냅니다.
5로 끝나는 카드는 벌점 2점, 0으로 끝나는 카드는 벌점 3점, 11의 배수는 벌점 5점, 55는 벌점 7점이며, 나머지는 모두 벌점 1점입니다.
'''라운드 끝내기'''
일단 라운드가 끝나면, 아무도 0점 이하로 떨어지지 않았다면, 새로운 라운드로 넘어갑니다. 만약 누군가가 모든 포인트를 잃었다면, 그 즉시 게임이 끝나고 가장 많은 포인트가 남은 사람이 이깁니다.
'''변경 가능 규칙'''
- '''카드 세트'''
Normal : 무조건 1~104까지의 카드를 사용합니다. 이에 따라 사용되지 않는 카드는 공개되지 않습니다.
Tactics : 플레이어 수에 따라 사용하는 카드의 수가 바뀝니다. 사용되지 않는 카드가 없도록 카드 수가 조정되며, 이에 따라 숫자의 범위는 1~(인원수*10+4)가 됩니다. 이 방식은 Normal에 비해 다른 전략과 카드 카운팅의 중요성이 커집니다.
Logic : Tactics와 동일하게 카드 장수를 조절하나, 카드 배분을 랜덤이 아닌 1장씩 가져가면서 덱을 만듭니다. 플레이 시간은 길어질 것이나, 운의 요소를 거의 배제할 수 있다는 점이 특이점입니다.
- '''카드 놓기'''
Normal : 게임 방법에 적힌 그대로, 아래와 같이 진행합니다 :
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드는 왼쪽부터 순서대로 놓아진다. 즉, 그 줄의 카드보다 작은 수의 카드는 놓이지 않는다.
Professional : 게임 방법과 다르게, 아래와 같이 진행합니다 :
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드의 방향은 제한이 없다. 즉, 편차가 더 작다면 줄의 맨 왼쪽에 놓아질수도 있다.
3bfe4b6bb48b9a56a54e1f60b4e1fc4c9f37b7ac
1225
1223
2016-12-10T15:42:17Z
Yooyou7
6164
굵기를 = =로 변경. 문법차입니다.
wikitext
text/x-wiki
=젝스님트!=
이 게임의 기본적인 목표는 카드를 가져가지 않고, 다른 플레이어로 하여금 갖고 가게 하는 것입니다. 모든 플레이어는 66포인트에서 시작합니다. 여기서 카드 위에 그려진 소머리 하나 당 1점씩 감점됩니다. 만일 모든 점수를 잃는 플레이어가 나오게 된다면, 해당 라운드에서 게임은 끝나게 되고, 가장 많은 포인트가 남은 사람이 승리하게 됩니다.
==게임방법==
모든 플레이어는 10장의 카드를 갖고 시작합니다. 라운드 시작 시 네 장의 카드는 테이블에 4열로 놓여집니다. 모든 플레이어는 각자 보이지 않게 카드를 한 장 고릅니다. 그리고 모두 골랐다면, 동시에 공개합니다. 카드가 공개되었다면, 카드가 놓이기 시작합니다. 가장 낮은 숫자부터 놓이기 시작합니다. 놓이는 규칙은 (Normal 기준으로) 다음과 같습니다. ('''카드 놓기'''를 참조하세요.)
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드는 왼쪽부터 순서대로 놓아진다. 즉, 그 줄의 카드보다 작은 수의 카드는 놓이지 않는다.
게임을 진행할수록, 각 열은 카드로 채워질 것입니다. 5장이 해당 열의 최대 갯수입니다. 만약 누군가가 해당 열의 여섯번째의 카드를 놓았다면, 그 열의 카드를 모두 벌점으로 가져가게 됩니다. 이때, 카드 위의 소머리 숫자만큼 포인트가 차감됩니다. 해당 플레이어가 놓았던 마지막 카드(여섯번 째 카드)가 해당 열의 첫 숫자로 진행됩니다.
만약 누군가가 모든 숫자들보다 낮은 숫자를 놓았다면 (즉, 카드를 놓을 수 있는 열이 없는 경우), 한 열을 선택하고 벌점으로 가져간 후, 자신이 놓을 카드를 그 열의 시작하는 카드로 놓습니다.
===소머리===
각 카드는 소머리가 있습니다. 이것은 해당 카드의 벌점을 나타냅니다.
5로 끝나는 카드는 벌점 2점, 0으로 끝나는 카드는 벌점 3점, 11의 배수는 벌점 5점, 55는 벌점 7점이며, 나머지는 모두 벌점 1점입니다.
===라운드 끝내기===
라운드가 끝나면, 아무도 0점 이하로 떨어지지 않았다면, 새로운 라운드로 넘어갑니다. 만약 누군가가 모든 포인트를 잃었다면, 그 즉시 게임이 끝나고 가장 많은 포인트가 남은 사람이 이깁니다.
==변경 가능 규칙==
===카드 세트===
Normal : 무조건 1~104까지의 카드를 사용합니다. 이에 따라 사용되지 않는 카드는 공개되지 않습니다.
Tactics : 플레이어 수에 따라 사용하는 카드의 수가 바뀝니다. 사용되지 않는 카드가 없도록 카드 수가 조정되며, 이에 따라 숫자의 범위는 1~(인원수*10+4)가 됩니다. 이 방식은 Normal에 비해 다른 전략과 카드 카운팅의 중요성이 커집니다.
Logic : Tactics와 동일하게 카드 장수를 조절하나, 카드 배분을 랜덤이 아닌 1장씩 가져가면서 덱을 만듭니다. 플레이 시간은 길어질 것이나, 운의 요소를 거의 배제할 수 있다는 점이 특이점입니다.
===카드 놓기===
Normal : 게임 방법에 적힌 그대로, 아래와 같이 진행합니다 :
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드는 왼쪽부터 순서대로 놓아진다. 즉, 그 줄의 카드보다 작은 수의 카드는 놓이지 않는다.
Professional : 게임 방법과 다르게, 아래와 같이 진행합니다 :
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드의 방향은 제한이 없다. 즉, 편차가 더 작다면 줄의 맨 왼쪽에 놓아질수도 있다.
49cf6373971c6ff95f750351cb8112808a2f77ad
Gamehelptargi
0
169
1206
1183
2016-06-15T06:35:08Z
Smler
6303
wikitext
text/x-wiki
Each round of play has the following stages:
# Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi.
# Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi.
# You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau.
You may only hold 3 gold and 10 goods total between rounds.
The game ends when a player has filled their tableau, or when the robber has completed one jog around the map.
게임을하는 동안 특수 카드 능력에서 얻은 승점 이외에, 당신 얻을수 있는 승점 ::
* 같은행이 동일한 카드로 이루어져 있으면 승점 4점.
* 같은행이 서로 다른 카드로 이루어져 있으면 승점 2점.
4d5d5e93780014fc45c0146bac0ce9a5c1b72a70
사용자:Prethousand flower
2
172
1207
2016-10-05T07:01:13Z
Prethousand flower
6335
새 문서: [[/번역/Gamehelpmetromaniab]]
wikitext
text/x-wiki
[[/번역/Gamehelpmetromaniab]]
5c8ba25e380cd89b1d2e60c9fe7d2a5109bdfddd
사용자:Prethousand flower/번역/Gamehelpmetromaniab
2
173
1208
2016-10-05T07:29:23Z
Prethousand flower
6335
새 문서: == 개요와 목표 == 메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다. ...
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 구역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
Take advantage of other players lines (for example, stations
are built wherever two lines meet ; you can win points at the
end by sharing the quickest trip), and try also to deroute or
even block off your opponents at the right time, to keep them
from well completing their lines!
At the end of the game, the city government will run seven
"test trips" between designated destinations, placed by the
players themselves during the game.
For each test trip, the fastest connection between the two
points will be rewarded with Public Utility Points, and the
player whose subways have the most points wins!
== GAME COMPONENTS & SET UP ==
'''게임 보드'''
To set up the board, take the four border pieces and put
them together. Take the six triangular "city" pieces, and
arrange them randomly within the border.
'''기물'''
플레이어는 각각 자기 색깔의 패를 받습니다.
점수패(score marker)를 점수표(scoring track)의 "0" 위치에 놓으십시오. 이 패는 열차를 표시합니다.
자신의 색깔에 맞는 노선 패를 가져가십시오. 노선 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나씩 두 개의 노선을 표시합니다.
각 노선에는 시작 지점(흰색 화살표)와 종착 지점(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
There are also twelve Destination markers. Each is marked
with a letter (A-F), and is paired with another Destination
marker. These will be the destinations that will be "tested"
after the building phase is complete. The summary of these
tests is in the upright corner of the board.
Finally, there are thirty "station" markers, which are set by the
side of the board, and are not controlled by any player.
The map is made up of smaller triangles, which are either
blank, have a destination symbol, or a lake/park. Along the
edge of the city are white arrows indicating where a subway
line starts, and black arrows indicating where they exit the city
== THE COURSE OF THE GAME ==
'''Installation'''
Take the destination markers and shuffle them letter-sidedown.
With 4 players, each player takes one Residential, one
Commercial, and one Entertainment Destination at random.
That player then secretly looks at his markers. If two have
the same letter, he puts one back and draws a new one until
all three have different letters. When all the players have
their three Destination markers, they flip them letter-side-up
in front of them, visible for others.
With 3 players, each player takes one more Destination marker.
With 2 players, each player gets 6 Destination markers: one
player gets the Destinations A,B,C,D,E,F shown on the left of
the gameboard test Summary, the other player uses the ones
on the right.
'''Player turn'''
The most "urbane" player begins.
Play goes clockwise starting with the first player. On one's
turn, the player MUST do one and only one of the following:
- Dig 3 tunnels (to continue one or both of his lines) or
- Build an intermediate station (on one of his lines)
'''Starting a line'''
Each player has two subway lines.
On his first turn, a player must, of course, begin a subway
line - but only one!
A subway line must start from an empty space with a white
arrow along the edge of the city. To start a line, place its first
tunnel, topped with its "start" marker, in any of these spaces.
Then continue normally the line in the city by digging the
remaining tunnels.
When you will begin your second subway line at any subsequent
turn, it must start on one of the "opposite" edges from
where your first line began.
'''Digging tunnels'''
Subway lines are built in the city by placing Tunnels in the
triangular spaces. Only one tunnel may be placed in a space,
and must conform to the following:
- A line must always be built from its terminus; and never "branch off"
- A line may not be continued with an acute angle. EXCEPTION: when a line terminates at a station, it may be built out from that station at any angle, even acute.
- A line may never make a loop or double back on itself
If you choose to dig tunnels on your turn, you MUST place
3 tunnels (unless it is only possible to place fewer).
If you have two lines, you may distribute your 3 tunnels
between them as you wish.
'''Special areas'''
The start or end spaces (with an arrow) along the edges of
the city can only be used to start or end a line.
Tunnel counters may never be placed on the park or the lake.
When a player places a tunnel counter on top of a destination
area, the player must place immediatly one of his
Destination markers on that tunnel piece (of the appropriate
type, of course), letter-side up.
If a player does not have the appropriate marker, the player
may not place that tunnel piece on the destination.
Furthermore, each player may only place one destination
marker per turn, and two destinations of the same letter
cannot touch, either on an angle or on the side.
'''Stations'''
Most of the stations are created while digging tunnels.
A station is immediately placed when:
- The line being dug joins another line. In this case, a station is placed where the two lines meet up.
- The line, which was running alongside another line, splits off from it. In this case, a station is placed where the line splits off.
- When a line, running alongside another line, changes side, NO STATION is placed.
The player scores 1 point for each destination area on the
board that touches the station.
He continues to dig tunnels after placing a station, if he still
has some left to build. (i.e., building a station like this does
not stop your tunneling.)
'''Intermediate stations'''
In lieu of digging tunnels, a player may use all his turn to
place one station anywhere on one of his lines, between two
preexisting stations. A starting or ending marker counts as a
station for this purpose.
Points are scored as for stations placed while digging tunnels.
'''Ending lines'''
A line ends on a space with a black arrow. The player digs
his last tunnel on that space, topped with an "End Line"
counter.
A line may not end on the same edge as it started, nor on an
adjoining edge to that "start edge," unless all the end spaces
on the allowed sides are already taken.
When a line ends, that player may immediately place an
intermediate station anywhere on the line. However, once a
line is completed (with this bonus station), the player may
never place an intermediate station on that line again
'''End of the building phase'''
Players continue building until one of the following occurs:
- A player has completed both of his lines
- A player places the last station available
- Five lines are either completed, or blocked and unable to be completed
Note : a line is blocked if it can no longer be extended, typically
because all the spaces at its end are already occupied,
forbidden, or has run out of tunnels.
Then all other players have one last turn to play.
After, scoring begins.
== THE SCORING PHASE ==
'''Lines scoring'''
First, scores are adjusted as follows:
- Players who completed both of their lines lose no station points.
- Players who completed only one line lose half their station points (rounded down)
- Players who completed none of their lines lose all their station points.
Adjust the scoring markers accordingly.
'''Test trip scoring'''
Each test trip runs between destination markers of the same
letter: A to A, then B to B, and so on. You can see the summary
of these trips in the upright corner of the board.
For each trip, determine the shortest route:
- a trip takes 1 minute to go from one station to another (no matter how many tunnel pieces are in between)
- and 3 minutes to change from one line to another.
A trip may have more than one fastest route.
Each player who has a line making up part of the fastest
route gets 3 points, plus a bonus of 3 points if he placed
one of the destination markers (i.e., if the marker is
on a tunnel piece of the player's color).
A player may only get points once for each test, even if the
player is involved in more than one route.
Players who are not involved in the fastest route never get
any point.
'''Impossible trips'''
Sometimes, a test run may be impossible.
If that is the case, a city investigation takes place to determine
the guilty party or parties:
- If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker.
- If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination.
- If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty.
The guilty party or parties loose 6 points
'''Final test'''
The last test run is between the park and the lake. Determine
the fastest route, as always. Each player involved in the fastest
route gets 5 points.
Important note : if your score goes beyond 20 points, move
your marker normally, but place one of your tunnels near the
20 to show that. If your score goes below 0 point, place one
of your tunnels near the 0.
== THE WINNER ==
At the end of the game, the player with the most points is
crowned King of the Subway - i.e., WINS.
If there is a tie, the winner is the player who finished the
most lines; if there is again a tie, the winner is the player who
placed the most tunnels.
If there is still a tie, litigation is the only possible solution.
== SPECIAL RULES ==
Two players
End of game: 3 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: the second version of the rules on this topic is not implemented on BGA.
Three players
End of game: 4 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: same as with four players.
== VARIANTS ==
Unfair Municipality (3-4 players)
Each player keeps his destination markers letter-side-down
in front of him. The markers are only revealed when they are
placed on a destination area in the city.
No Corruption (3-4 players)
Ah, everything is straight and clear… Because each player
takes pre-etablished destination markers and keeps them in
front of him, letter-face-up, of course!
4 players
Player 1: A Residential, B Commercial, C Entertainment
Player 2: D Residential, A Commercial, E Entertainment
Player 3: F Residential, E Commercial, B Entertainment
Player 4: C Residential, D Commercial, F Entertainment
3 players :
Player 1: A & D Residential, B Commercial, C Entertainment
Player 2: C Residential, A & E Commercial, F Entertainment
Player 3: F Residential, D Commercial, B & E Entertainment
Metromania Official Rulebook, Spiel or Face
c2132d2d8235974226bdceba209fa4563399adbe
1209
1208
2016-10-07T05:40:59Z
Prethousand flower
6335
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
Take advantage of other players lines (for example, stations
are built wherever two lines meet ; you can win points at the
end by sharing the quickest trip), and try also to deroute or
even block off your opponents at the right time, to keep them
from well completing their lines!
At the end of the game, the city government will run seven
"test trips" between designated destinations, placed by the
players themselves during the game.
For each test trip, the fastest connection between the two
points will be rewarded with Public Utility Points, and the
player whose subways have the most points wins!
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 받습니다.
점수패(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 터널 패를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 시작 지점 패(흰색 화살표)와 종착 지점 패(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 목적지 패(Destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다.
이 짝을 이룬 2개의 목적지는 시험 운행의 시종착지가 됩니다. 시험 운행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝이 요약되어 있습니다.
마지막으로, 30개의 역 패(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 갖지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''시작'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
The most "urbane" player begins.
Play goes clockwise starting with the first player.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 도시의 육각형 변 중 첫 번째 노선이 시작한 변과 그에 인접한 2개의 변에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
- A line may never make a loop or double back on itself
If you choose to dig tunnels on your turn, you MUST place
3 tunnels (unless it is only possible to place fewer).
If you have two lines, you may distribute your 3 tunnels
between them as you wish.
'''Special areas'''
The start or end spaces (with an arrow) along the edges of
the city can only be used to start or end a line.
Tunnel counters may never be placed on the park or the lake.
When a player places a tunnel counter on top of a destination
area, the player must place immediatly one of his
Destination markers on that tunnel piece (of the appropriate
type, of course), letter-side up.
If a player does not have the appropriate marker, the player
may not place that tunnel piece on the destination.
Furthermore, each player may only place one destination
marker per turn, and two destinations of the same letter
cannot touch, either on an angle or on the side.
'''Stations'''
Most of the stations are created while digging tunnels.
A station is immediately placed when:
- The line being dug joins another line. In this case, a station is placed where the two lines meet up.
- The line, which was running alongside another line, splits off from it. In this case, a station is placed where the line splits off.
- When a line, running alongside another line, changes side, NO STATION is placed.
The player scores 1 point for each destination area on the
board that touches the station.
He continues to dig tunnels after placing a station, if he still
has some left to build. (i.e., building a station like this does
not stop your tunneling.)
'''Intermediate stations'''
In lieu of digging tunnels, a player may use all his turn to
place one station anywhere on one of his lines, between two
preexisting stations. A starting or ending marker counts as a
station for this purpose.
Points are scored as for stations placed while digging tunnels.
'''Ending lines'''
A line ends on a space with a black arrow. The player digs
his last tunnel on that space, topped with an "End Line"
counter.
A line may not end on the same edge as it started, nor on an
adjoining edge to that "start edge," unless all the end spaces
on the allowed sides are already taken.
When a line ends, that player may immediately place an
intermediate station anywhere on the line. However, once a
line is completed (with this bonus station), the player may
never place an intermediate station on that line again
'''End of the building phase'''
Players continue building until one of the following occurs:
- A player has completed both of his lines
- A player places the last station available
- Five lines are either completed, or blocked and unable to be completed
Note : a line is blocked if it can no longer be extended, typically
because all the spaces at its end are already occupied,
forbidden, or has run out of tunnels.
Then all other players have one last turn to play.
After, scoring begins.
== THE SCORING PHASE ==
'''Lines scoring'''
First, scores are adjusted as follows:
- Players who completed both of their lines lose no station points.
- Players who completed only one line lose half their station points (rounded down)
- Players who completed none of their lines lose all their station points.
Adjust the scoring markers accordingly.
'''Test trip scoring'''
Each test trip runs between destination markers of the same
letter: A to A, then B to B, and so on. You can see the summary
of these trips in the upright corner of the board.
For each trip, determine the shortest route:
- a trip takes 1 minute to go from one station to another (no matter how many tunnel pieces are in between)
- and 3 minutes to change from one line to another.
A trip may have more than one fastest route.
Each player who has a line making up part of the fastest
route gets 3 points, plus a bonus of 3 points if he placed
one of the destination markers (i.e., if the marker is
on a tunnel piece of the player's color).
A player may only get points once for each test, even if the
player is involved in more than one route.
Players who are not involved in the fastest route never get
any point.
'''Impossible trips'''
Sometimes, a test run may be impossible.
If that is the case, a city investigation takes place to determine
the guilty party or parties:
- If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker.
- If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination.
- If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty.
The guilty party or parties loose 6 points
'''Final test'''
The last test run is between the park and the lake. Determine
the fastest route, as always. Each player involved in the fastest
route gets 5 points.
Important note : if your score goes beyond 20 points, move
your marker normally, but place one of your tunnels near the
20 to show that. If your score goes below 0 point, place one
of your tunnels near the 0.
== THE WINNER ==
At the end of the game, the player with the most points is
crowned King of the Subway - i.e., WINS.
If there is a tie, the winner is the player who finished the
most lines; if there is again a tie, the winner is the player who
placed the most tunnels.
If there is still a tie, litigation is the only possible solution.
== SPECIAL RULES ==
Two players
End of game: 3 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: the second version of the rules on this topic is not implemented on BGA.
Three players
End of game: 4 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: same as with four players.
== VARIANTS ==
Unfair Municipality (3-4 players)
Each player keeps his destination markers letter-side-down
in front of him. The markers are only revealed when they are
placed on a destination area in the city.
No Corruption (3-4 players)
Ah, everything is straight and clear… Because each player
takes pre-etablished destination markers and keeps them in
front of him, letter-face-up, of course!
4 players
Player 1: A Residential, B Commercial, C Entertainment
Player 2: D Residential, A Commercial, E Entertainment
Player 3: F Residential, E Commercial, B Entertainment
Player 4: C Residential, D Commercial, F Entertainment
3 players :
Player 1: A & D Residential, B Commercial, C Entertainment
Player 2: C Residential, A & E Commercial, F Entertainment
Player 3: F Residential, D Commercial, B & E Entertainment
Metromania Official Rulebook, Spiel or Face
714fad4fecd409c1f77aa58d53ab5aa1a5dfec35
1210
1209
2016-10-07T16:07:19Z
Prethousand flower
6335
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
Take advantage of other players lines (for example, stations
are built wherever two lines meet ; you can win points at the
end by sharing the quickest trip), and try also to deroute or
even block off your opponents at the right time, to keep them
from well completing their lines!
At the end of the game, the city government will run seven
"test trips" between designated destinations, placed by the
players themselves during the game.
For each test trip, the fastest connection between the two
points will be rewarded with Public Utility Points, and the
player whose subways have the most points wins!
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 받습니다.
점수패(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 터널 패를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 시작 지점 패(흰색 화살표)와 종착 지점 패(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 목적지 패(Destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다.
이 짝을 이룬 2개의 목적지는 시험 운행의 시종착지가 됩니다. 시험 운행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝이 요약되어 있습니다.
마지막으로, 30개의 역 패(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 갖지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''시작'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
The most "urbane" player begins.
Play goes clockwise starting with the first player.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
:- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
:- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 도시의 육각형 변 중 첫 번째 노선이 시작한 변과 그에 인접한 2개의 변에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
:- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
:- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
:- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
:- 터널을 파는 턴에서는 반드시 3개의 터널을 건설해야 합니다. 단, 터널을 건설할 수 있는 공간이 그보다 적을 경우에는 예외입니다. 반드시 3개의 터널을 한 노선에 지을 필요는 없으며 두 개의 노선에 지은 터널의 갯수의 합이 3개여도 가능합니다.
'''특별 구역'''
도시 가장자리의 (화살표가 있는) 시작 지점과 종착 지점에는 노선의 시작이나 끝이 되는 터널 패만 올릴 수 있으며 그 외의 용도로는 사용할 수 없습니다.
공원과 호수 위에는 터널 패를 놓을 수 업습니다.
목적지가 그려진 위치에 터널 패를 놓은 후에 바로 그 위에 자신의 목적지 패를 글자가 쓰여 있는 부분이 위로 오도록 놓습니다. 물론 지도의 목적지와 목적지 패의 목적지는 같은 종류여야 합니다.
만약 같은 종류의 목적지 패가 없다면, 그 목적지 위치에는 터널을 건설할 수 없습니다.
또한, 각 플레이어는 한 턴에 목적지 패를 한 개만 올려놓을 수 있고, 지도상에서 다른 종류의 목적지끼리 서로 꼭지점 또는 변에서 접할 때 그 두 목적지에 서로 같은 글자가 쓰여진 목적지 패를 놓을 수 없습니다.
'''역'''
다음과 같은 경우엔 역이 자동으로 만들어집니다:
:- 노선이 다른 노선과 교차할 때, 두 노선이 만나는 지점에 역 패를 놓습니다.
:- 노선이 다른 노선과 나란히 가다 갈라질 때, 갈라지는 지점에 역 패를 놓습니다. 단, 나란히 놓인 두 노선이 위치만 바뀌는 경우에는 놓지 않습니다.
자신의 역이 그 꼭지점 위에 놓여 있는 목적지의 갯수만큼 1점을 얻습니다.
'''Intermediate stations'''
In lieu of digging tunnels, a player may use all his turn to
place one station anywhere on one of his lines, between two
preexisting stations. A starting or ending marker counts as a
station for this purpose.
Points are scored as for stations placed while digging tunnels.
'''Ending lines'''
A line ends on a space with a black arrow. The player digs
his last tunnel on that space, topped with an "End Line"
counter.
A line may not end on the same edge as it started, nor on an
adjoining edge to that "start edge," unless all the end spaces
on the allowed sides are already taken.
When a line ends, that player may immediately place an
intermediate station anywhere on the line. However, once a
line is completed (with this bonus station), the player may
never place an intermediate station on that line again
'''End of the building phase'''
Players continue building until one of the following occurs:
- A player has completed both of his lines
- A player places the last station available
- Five lines are either completed, or blocked and unable to be completed
Note : a line is blocked if it can no longer be extended, typically
because all the spaces at its end are already occupied,
forbidden, or has run out of tunnels.
Then all other players have one last turn to play.
After, scoring begins.
== THE SCORING PHASE ==
'''Lines scoring'''
First, scores are adjusted as follows:
- Players who completed both of their lines lose no station points.
- Players who completed only one line lose half their station points (rounded down)
- Players who completed none of their lines lose all their station points.
Adjust the scoring markers accordingly.
'''Test trip scoring'''
Each test trip runs between destination markers of the same
letter: A to A, then B to B, and so on. You can see the summary
of these trips in the upright corner of the board.
For each trip, determine the shortest route:
- a trip takes 1 minute to go from one station to another (no matter how many tunnel pieces are in between)
- and 3 minutes to change from one line to another.
A trip may have more than one fastest route.
Each player who has a line making up part of the fastest
route gets 3 points, plus a bonus of 3 points if he placed
one of the destination markers (i.e., if the marker is
on a tunnel piece of the player's color).
A player may only get points once for each test, even if the
player is involved in more than one route.
Players who are not involved in the fastest route never get
any point.
'''Impossible trips'''
Sometimes, a test run may be impossible.
If that is the case, a city investigation takes place to determine
the guilty party or parties:
- If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker.
- If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination.
- If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty.
The guilty party or parties loose 6 points
'''Final test'''
The last test run is between the park and the lake. Determine
the fastest route, as always. Each player involved in the fastest
route gets 5 points.
Important note : if your score goes beyond 20 points, move
your marker normally, but place one of your tunnels near the
20 to show that. If your score goes below 0 point, place one
of your tunnels near the 0.
== THE WINNER ==
At the end of the game, the player with the most points is
crowned King of the Subway - i.e., WINS.
If there is a tie, the winner is the player who finished the
most lines; if there is again a tie, the winner is the player who
placed the most tunnels.
If there is still a tie, litigation is the only possible solution.
== SPECIAL RULES ==
Two players
End of game: 3 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: the second version of the rules on this topic is not implemented on BGA.
Three players
End of game: 4 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: same as with four players.
== VARIANTS ==
Unfair Municipality (3-4 players)
Each player keeps his destination markers letter-side-down
in front of him. The markers are only revealed when they are
placed on a destination area in the city.
No Corruption (3-4 players)
Ah, everything is straight and clear… Because each player
takes pre-etablished destination markers and keeps them in
front of him, letter-face-up, of course!
4 players
Player 1: A Residential, B Commercial, C Entertainment
Player 2: D Residential, A Commercial, E Entertainment
Player 3: F Residential, E Commercial, B Entertainment
Player 4: C Residential, D Commercial, F Entertainment
3 players :
Player 1: A & D Residential, B Commercial, C Entertainment
Player 2: C Residential, A & E Commercial, F Entertainment
Player 3: F Residential, D Commercial, B & E Entertainment
Metromania Official Rulebook, Spiel or Face
032f4db3900f03cfa4ddff553b28ef7ff6e8c22c
1211
1210
2016-10-07T16:35:56Z
Prethousand flower
6335
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
Take advantage of other players lines (for example, stations
are built wherever two lines meet ; you can win points at the
end by sharing the quickest trip), and try also to deroute or
even block off your opponents at the right time, to keep them
from well completing their lines!
At the end of the game, the city government will run seven
"test trips" between designated destinations, placed by the
players themselves during the game.
For each test trip, the fastest connection between the two
points will be rewarded with Public Utility Points, and the
player whose subways have the most points wins!
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 받습니다.
점수 패(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 터널 패를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 시작 지점 패(흰색 화살표)와 종착 지점 패(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 목적지 패(Destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다.
이 짝을 이룬 2개의 목적지는 시험 운행의 시종착지가 됩니다. 시험 운행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝이 요약되어 있습니다.
마지막으로, 30개의 역 패(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 갖지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''시작'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
The most "urbane" player begins.
Play goes clockwise starting with the first player.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
:- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
:- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 도시의 육각형 모서리 중 첫 번째 노선이 시작한 모서리와 그에 인접한 2개의 모서리에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
:- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
:- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
:- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
:- 터널을 파는 턴에서는 반드시 3개의 터널을 건설해야 합니다. 단, 터널을 건설할 수 있는 공간이 그보다 적을 경우에는 예외입니다. 반드시 3개의 터널을 한 노선에 지을 필요는 없으며 두 개의 노선에 지은 터널의 갯수의 합이 3개여도 가능합니다.
'''특별 구역'''
도시 가장자리의 (화살표가 있는) 시작 지점과 종착 지점에는 노선의 시작이나 끝이 되는 터널 패만 올릴 수 있으며 그 외의 용도로는 사용할 수 없습니다.
공원과 호수 위에는 터널 패를 놓을 수 없습니다.
목적지가 그려진 위치에 터널 패를 놓은 후에 바로 그 위에 자신의 목적지 패를 글자가 쓰여 있는 부분이 위로 오도록 놓습니다. 물론 지도의 목적지와 목적지 패의 목적지는 같은 종류여야 합니다.
만약 같은 종류의 목적지 패가 없다면, 그 목적지 위치에는 터널을 건설할 수 없습니다.
또한, 각 플레이어는 한 턴에 목적지 패를 한 개만 올려놓을 수 있고, 지도상에서 다른 종류의 목적지끼리 꼭지점 또는 모서리가 접할 때 그 두 목적지에 서로 같은 글자가 쓰여진 목적지 패를 놓을 수 없습니다.
'''역'''
다음과 같은 경우엔 역이 자동으로 만들어집니다:
:- 노선이 다른 노선과 교차할 때, 두 노선이 만나는 지점에 역 패를 놓습니다.
:- 노선이 다른 노선과 나란히 가다 갈라질 때, 갈라지는 지점에 역 패를 놓습니다. 단, 나란히 놓인 두 노선이 위치만 바뀌는 경우에는 놓지 않습니다.
자신의 노선 위의 역이 지도의 목적지가 그려진 삼각형의 꼭지점에 놓일 때, 그런 목적지의 갯수만큼 1점을 얻습니다.
'''보통역'''
터널을 파는 대신에, 플레이어는 한 턴에 한 개의 역을 건설할 수 있습니다. 자동으로 건설된 역과 점수 계산의 차이는 없습니다.
'''노선 완공하기'''
노선은 검은 화살표가 있는 공간에서 끝납니다. 노선은 도시의 6개 모서리 중 그 노선이 시작한 모서리와 그 양 옆의 두 모서리에서는 끝날 수 없습니다. 단, 나머지 세 모서리의 종착 지점이 모두 선점되어 갈 곳이 없는 경우에는 예외입니다.
노선이 완공될 때, 완공한 플레이어는 즉시 그 노선의 아무 곳에나 보통역을 하나 건설할 수 있습니다. 그러나 그 이후에 그 노선에는 보통역을 건설할 수 없습니다.
'''건설 페이즈의 종료'''
다음 중 한 조건을 만족할 때까지 노선을 건설할 수 있습니다:
:- 한 플레이어가 2개의 노선을 모두 완공했을 때
:- 모든 역 패가 사용되었을 때
:- 완공되거나 더이상 완공될 수 없는 노선이 5개 이상일 때(완공될 수 없는 노선이란 해당 노선이 뻗어나갈 수 있는 지점이 모두 선점되었거나 터널 패를 놓을 수 없는 공간(공원·호수)인 경우, 또는 그 노선의 모든 터널 패가 사용된 경우를 말하며, 이 이유로 건설 페이즈가 종료될 때는 다른 모든 플레이어에게 한 턴을 더 준 후에 종료합니다.)
이후 점수를 계산합니다.
== 점수 계산 ==
'''노선 점수'''
플레이어가 건설한 노선에 따른 점수는 다음과 같이 계산합니다:
:- 자신의 노선 2개를 모두 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 온전히 가져갑니다.
:- 자신의 노선을 한 개만 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 반만 가져갑니다.
:- 자신의 노선을 한 개도 완공하지 못한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 모두 잃습니다.
이 기준에 따라 점수 패를 이동하십시오.
'''시험 운행 점수'''
같은 글자가 쓰인 목적지 패 간에 시험 운행이 시행됩니다.
:- 운행은 한 역에서 다음 역까지 가는 데 1분이 소요됩니다. (그 사이에 몇 개의 터널 패가 있는지는 상관없습니다)
:- 다른 노선으로 갈아타는 데는 3분이 소요됩니다.
For each trip, determine the shortest route:
- a trip takes 1 minute to go from one station to another (no matter how many tunnel pieces are in between)
- and 3 minutes to change from one line to another.
A trip may have more than one fastest route.
Each player who has a line making up part of the fastest
route gets 3 points, plus a bonus of 3 points if he placed
one of the destination markers (i.e., if the marker is
on a tunnel piece of the player's color).
A player may only get points once for each test, even if the
player is involved in more than one route.
Players who are not involved in the fastest route never get
any point.
'''Impossible trips'''
Sometimes, a test run may be impossible.
If that is the case, a city investigation takes place to determine
the guilty party or parties:
- If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker.
- If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination.
- If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty.
The guilty party or parties loose 6 points
'''Final test'''
The last test run is between the park and the lake. Determine
the fastest route, as always. Each player involved in the fastest
route gets 5 points.
Important note : if your score goes beyond 20 points, move
your marker normally, but place one of your tunnels near the
20 to show that. If your score goes below 0 point, place one
of your tunnels near the 0.
== THE WINNER ==
At the end of the game, the player with the most points is
crowned King of the Subway - i.e., WINS.
If there is a tie, the winner is the player who finished the
most lines; if there is again a tie, the winner is the player who
placed the most tunnels.
If there is still a tie, litigation is the only possible solution.
== SPECIAL RULES ==
Two players
End of game: 3 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: the second version of the rules on this topic is not implemented on BGA.
Three players
End of game: 4 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: same as with four players.
== VARIANTS ==
Unfair Municipality (3-4 players)
Each player keeps his destination markers letter-side-down
in front of him. The markers are only revealed when they are
placed on a destination area in the city.
No Corruption (3-4 players)
Ah, everything is straight and clear… Because each player
takes pre-etablished destination markers and keeps them in
front of him, letter-face-up, of course!
4 players
Player 1: A Residential, B Commercial, C Entertainment
Player 2: D Residential, A Commercial, E Entertainment
Player 3: F Residential, E Commercial, B Entertainment
Player 4: C Residential, D Commercial, F Entertainment
3 players :
Player 1: A & D Residential, B Commercial, C Entertainment
Player 2: C Residential, A & E Commercial, F Entertainment
Player 3: F Residential, D Commercial, B & E Entertainment
Metromania Official Rulebook, Spiel or Face
f480e10ae4e18d4bad797b7eb766c7921eba62df
1212
1211
2016-10-10T00:45:46Z
Prethousand flower
6335
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
Take advantage of other players lines (for example, stations
are built wherever two lines meet ; you can win points at the
end by sharing the quickest trip), and try also to deroute or
even block off your opponents at the right time, to keep them
from well completing their lines!
At the end of the game, the city government will run seven
"test trips" between designated destinations, placed by the
players themselves during the game.
For each test trip, the fastest connection between the two
points will be rewarded with Public Utility Points, and the
player whose subways have the most points wins!
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 받습니다.
점수 패(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 터널 패를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 시작 지점 패(흰색 화살표)와 종착 지점 패(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 목적지 패(Destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다.
이 짝을 이룬 2개의 목적지는 시험 운행의 시종착지가 됩니다. 시험 운행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝이 요약되어 있습니다.
마지막으로, 30개의 역 패(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 갖지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''시작'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
게임은 가장 "도시적인"(urbane) 플레이어부터 시작하며 턴은 그로부터 시계방향으로 주어집니다.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
:- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
:- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 도시의 육각형 모서리 중 첫 번째 노선이 시작한 모서리와 그에 인접한 2개의 모서리에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
:- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
:- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
:- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
:- 터널을 파는 턴에서는 반드시 3개의 터널을 건설해야 합니다. 단, 터널을 건설할 수 있는 공간이 그보다 적을 경우에는 예외입니다. 반드시 3개의 터널을 한 노선에 지을 필요는 없으며 두 개의 노선에 지은 터널의 갯수의 합이 3개여도 가능합니다.
'''특별 구역'''
도시 가장자리의 (화살표가 있는) 시작 지점과 종착 지점에는 노선의 시작이나 끝이 되는 터널 패만 올릴 수 있으며 그 외의 용도로는 사용할 수 없습니다.
공원과 호수 위에는 터널 패를 놓을 수 없습니다.
목적지가 그려진 위치에 터널 패를 놓은 후에 바로 그 위에 자신의 목적지 패를 글자가 쓰여 있는 부분이 위로 오도록 놓습니다. 물론 지도의 목적지와 목적지 패의 목적지는 같은 종류여야 합니다.
만약 같은 종류의 목적지 패가 없다면, 그 목적지 위치에는 터널을 건설할 수 없습니다.
또한, 각 플레이어는 한 턴에 목적지 패를 한 개만 올려놓을 수 있고, 지도상에서 다른 종류의 목적지끼리 꼭지점 또는 모서리가 접할 때 그 두 목적지에 서로 같은 글자가 쓰여진 목적지 패를 놓을 수 없습니다.
'''역'''
다음과 같은 경우엔 역이 자동으로 만들어집니다:
:- 노선이 다른 노선과 교차할 때, 두 노선이 만나는 지점에 역 패를 놓습니다.
:- 노선이 다른 노선과 나란히 가다 갈라질 때, 갈라지는 지점에 역 패를 놓습니다. 단, 나란히 놓인 두 노선이 위치만 바뀌는 경우에는 놓지 않습니다.
자신의 노선 위의 역이 지도의 목적지가 그려진 삼각형의 꼭지점에 놓일 때, 그런 목적지의 갯수만큼 1점을 얻습니다.
'''보통역'''
터널을 파는 대신에, 플레이어는 한 턴에 한 개의 역을 건설할 수 있습니다. 자동으로 건설된 역과 점수 계산의 차이는 없습니다.
'''노선 완공하기'''
노선은 검은 화살표가 있는 공간에서 끝납니다. 노선은 도시의 6개 모서리 중 그 노선이 시작한 모서리와 그 양 옆의 두 모서리에서는 끝날 수 없습니다. 단, 나머지 세 모서리의 종착 지점이 모두 선점되어 갈 곳이 없는 경우에는 예외입니다.
노선이 완공될 때, 완공한 플레이어는 즉시 그 노선의 아무 곳에나 보통역을 하나 건설할 수 있습니다. 그러나 그 이후에 그 노선에는 보통역을 건설할 수 없습니다.
'''건설 페이즈의 종료'''
다음 중 한 조건을 만족할 때까지 노선을 건설할 수 있습니다:
:- 한 플레이어가 2개의 노선을 모두 완공했을 때
:- 모든 역 패가 사용되었을 때
:- 완공된 노선과 더이상 완공될 수 없는 노선이 합해서 5개 이상일 때(완공될 수 없는 노선이란 해당 노선이 뻗어나갈 수 있는 지점이 모두 선점되었거나 터널 패를 놓을 수 없는 공간(공원·호수)인 경우, 또는 그 노선의 모든 터널 패가 사용된 경우를 말하며, 이 이유로 건설 페이즈가 종료될 때는 다른 모든 플레이어에게 한 턴을 더 준 후에 종료합니다.)
이후 점수를 계산합니다.
== 점수 계산 ==
'''노선 점수'''
플레이어가 건설한 노선에 따른 점수는 다음과 같이 계산합니다:
:- 자신의 노선 2개를 모두 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 온전히 가져갑니다.
:- 자신의 노선을 한 개만 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 반만 가져갑니다.
:- 자신의 노선을 한 개도 완공하지 못한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 모두 잃습니다.
이 기준에 따라 점수 패를 이동하십시오.
'''시험 운행 점수'''
같은 글자가 쓰인 목적지 패 간에 시험 운행이 시행됩니다. 각 운행에서 가장 적은 시간이 소요되는 경로를 계산합니다.
:- 운행은 한 역에서 다음 역까지 가는 데 1분이 소요됩니다. (그 사이에 몇 개의 터널 패가 있는지는 상관없습니다)
:- 다른 노선으로 갈아타는 데는 3분이 소요됩니다.
최단 경로가 여러 개일 수 있습니다. 각 플레이어는
A trip may have more than one fastest route.
Each player who has a line making up part of the fastest
route gets 3 points, plus a bonus of 3 points if he placed
one of the destination markers (i.e., if the marker is
on a tunnel piece of the player's color).
A player may only get points once for each test, even if the
player is involved in more than one route.
Players who are not involved in the fastest route never get
any point.
'''Impossible trips'''
Sometimes, a test run may be impossible.
If that is the case, a city investigation takes place to determine
the guilty party or parties:
- If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker.
- If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination.
- If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty.
The guilty party or parties loose 6 points
'''Final test'''
The last test run is between the park and the lake. Determine
the fastest route, as always. Each player involved in the fastest
route gets 5 points.
Important note : if your score goes beyond 20 points, move
your marker normally, but place one of your tunnels near the
20 to show that. If your score goes below 0 point, place one
of your tunnels near the 0.
== THE WINNER ==
At the end of the game, the player with the most points is
crowned King of the Subway - i.e., WINS.
If there is a tie, the winner is the player who finished the
most lines; if there is again a tie, the winner is the player who
placed the most tunnels.
If there is still a tie, litigation is the only possible solution.
== SPECIAL RULES ==
Two players
End of game: 3 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: the second version of the rules on this topic is not implemented on BGA.
Three players
End of game: 4 lines finished and/or blocked ends the building
phase. The other conditions still unchanged.
Test trip scoring: same as with four players.
== VARIANTS ==
Unfair Municipality (3-4 players)
Each player keeps his destination markers letter-side-down
in front of him. The markers are only revealed when they are
placed on a destination area in the city.
No Corruption (3-4 players)
Ah, everything is straight and clear… Because each player
takes pre-etablished destination markers and keeps them in
front of him, letter-face-up, of course!
4 players
Player 1: A Residential, B Commercial, C Entertainment
Player 2: D Residential, A Commercial, E Entertainment
Player 3: F Residential, E Commercial, B Entertainment
Player 4: C Residential, D Commercial, F Entertainment
3 players :
Player 1: A & D Residential, B Commercial, C Entertainment
Player 2: C Residential, A & E Commercial, F Entertainment
Player 3: F Residential, D Commercial, B & E Entertainment
Metromania Official Rulebook, Spiel or Face
2fec40cc1336c80abe7efc2f5dcaab17ffafc439
1213
1212
2016-10-11T06:24:06Z
Prethousand flower
6335
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
Take advantage of other players lines (for example, stations
are built wherever two lines meet ; you can win points at the
end by sharing the quickest trip), and try also to deroute or
even block off your opponents at the right time, to keep them
from well completing their lines!
At the end of the game, the city government will run seven
"test trips" between designated destinations, placed by the
players themselves during the game.
For each test trip, the fastest connection between the two
points will be rewarded with Public Utility Points, and the
player whose subways have the most points wins!
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 받습니다.
점수 패(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 터널 패를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 시작 지점 패(흰색 화살표)와 종착 지점 패(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 목적지 패(Destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다.
이 짝을 이룬 2개의 목적지는 시험 운행의 시종착지가 됩니다. 시험 운행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝이 요약되어 있습니다.
마지막으로, 30개의 역 패(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 갖지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''시작'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
게임은 가장 "도시적인"(urbane) 플레이어부터 시작하며 턴은 그로부터 시계방향으로 주어집니다.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
:- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
:- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 도시의 육각형 모서리 중 첫 번째 노선이 시작한 모서리와 그에 인접한 2개의 모서리에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
:- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
:- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
:- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
:- 터널을 파는 턴에서는 반드시 3개의 터널을 건설해야 합니다. 단, 터널을 건설할 수 있는 공간이 그보다 적을 경우에는 예외입니다. 반드시 3개의 터널을 한 노선에 지을 필요는 없으며 두 개의 노선에 지은 터널의 갯수의 합이 3개여도 가능합니다.
'''특별 구역'''
도시 가장자리의 (화살표가 있는) 시작 지점과 종착 지점에는 노선의 시작이나 끝이 되는 터널 패만 올릴 수 있으며 그 외의 용도로는 사용할 수 없습니다.
공원과 호수 위에는 터널 패를 놓을 수 없습니다.
목적지가 그려진 위치에 터널 패를 놓은 후에 바로 그 위에 자신의 목적지 패를 글자가 쓰여 있는 부분이 위로 오도록 놓습니다. 물론 지도의 목적지와 목적지 패의 목적지는 같은 종류여야 합니다.
만약 같은 종류의 목적지 패가 없다면, 그 목적지 위치에는 터널을 건설할 수 없습니다.
또한, 각 플레이어는 한 턴에 목적지 패를 한 개만 올려놓을 수 있고, 지도상에서 다른 종류의 목적지끼리 꼭지점 또는 모서리가 접할 때 그 두 목적지에 서로 같은 글자가 쓰여진 목적지 패를 놓을 수 없습니다.
'''역'''
다음과 같은 경우엔 역이 자동으로 만들어집니다:
:- 노선이 다른 노선과 교차할 때, 두 노선이 만나는 지점에 역 패를 놓습니다.
:- 노선이 다른 노선과 나란히 가다 갈라질 때, 갈라지는 지점에 역 패를 놓습니다. 단, 나란히 놓인 두 노선이 위치만 바뀌는 경우에는 놓지 않습니다.
자신의 노선 위의 역이 지도의 목적지가 그려진 삼각형의 꼭지점에 놓일 때, 그런 목적지의 갯수만큼 1점을 얻습니다.
'''보통역'''
터널을 파는 대신에, 플레이어는 한 턴에 한 개의 역을 건설할 수 있습니다. 자동으로 건설된 역과 점수 계산의 차이는 없습니다.
'''노선 완공하기'''
노선은 검은 화살표가 있는 공간에서 끝납니다. 노선은 도시의 6개 모서리 중 그 노선이 시작한 모서리와 그 양 옆의 두 모서리에서는 끝날 수 없습니다. 단, 나머지 세 모서리의 종착 지점이 모두 선점되어 갈 곳이 없는 경우에는 예외입니다.
노선이 완공될 때, 완공한 플레이어는 즉시 그 노선의 아무 곳에나 보통역을 하나 건설할 수 있습니다. 그러나 그 이후에 그 노선에는 보통역을 건설할 수 없습니다.
'''건설 페이즈의 종료'''
다음 중 한 조건을 만족할 때까지 노선을 건설할 수 있습니다:
:- 한 플레이어가 2개의 노선을 모두 완공했을 때
:- 모든 역 패가 사용되었을 때
:- 완공된 노선과 더이상 완공될 수 없는 노선이 합해서 5개 이상일 때(완공될 수 없는 노선이란 해당 노선이 뻗어나갈 수 있는 지점이 모두 선점되었거나 터널 패를 놓을 수 없는 공간(공원·호수)인 경우, 또는 그 노선의 모든 터널 패가 사용된 경우를 말하며, 이 이유로 건설 페이즈가 종료될 때는 다른 모든 플레이어에게 한 턴을 더 준 후에 종료합니다.)
이후 점수를 계산합니다.
== 점수 계산 ==
'''노선 점수'''
플레이어가 건설한 노선에 따른 점수는 다음과 같이 계산합니다:
:- 자신의 노선 2개를 모두 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 온전히 가져갑니다.
:- 자신의 노선을 한 개만 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 반만 가져갑니다.
:- 자신의 노선을 한 개도 완공하지 못한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 모두 잃습니다.
이 기준에 따라 점수 패를 이동하십시오.
'''시험 운행 점수'''
같은 글자가 쓰인 목적지 패 간에 시험 운행이 시행됩니다. 각 운행에서 가장 적은 시간이 소요되는 경로를 계산합니다.
:- 운행은 한 역에서 다음 역까지 가는 데 1분이 소요됩니다. (그 사이에 몇 개의 터널 패가 있는지는 상관없습니다)
:- 다른 노선으로 갈아타는 데는 3분이 소요됩니다.
가장 적은 시간이 소요되는 경로를 구성하는 노선을 소유하고 있는 모든 플레이어는 3점씩 받고, 시험 운행의 시종착점인 목적지 패를 놓은 플레이어는 3점씩을 더 받습니다.
가장 적은 시간이 소요되는 경로가 여러 개일 수도 있습니다. 한 플레이어의 노선이 여러 개의 경로에 모두 관여하고 있더라도 한 시험 운행 구간에서 플레이어는 한 번만 점수를 얻을 수 있습니다.
가장 적은 시간이 소요되는 경로에 자신의 노선이 없는 플레이어는 점수를 얻을 수 없습니다.
'''운행 불가능'''
노선의 건설 상황에 따라 시험 운행이 불가능할 경우도 있습니다.
이런 경우엔, 도시에서 조사 위원회를 구성해 그 책임이 있는 플레이어(들)에게 벌점을 부과합니다.
:- 목적지 패가 보드 위에 놓이지 않았다면, 그 목적지 패를 놓지 못한 플레이어에게 책임이 있습니다.
:- 목적지 패가 놓여졌지만 그 위에 역이 지어지지 않았다면, 역이 지어지지 못한 목적지 패를 놓은 플레이어에게 책임이 있습니다.
:- 두 목적지 패가 모두 놓여졌지만 둘을 연결하는 경로가 존재하지 않는다면, 그 두 목적지 패를 놓은 플레이어에게 책임이 있습니다.
책임이 있는 플레이어(들)은 6점을 잃습니다.
'''시험 운행 결승'''
마지막 시험 운행은 공원과 호수 사이에서 시행됩니다. 마찬가지로 가장 적은 시간이 소요되는 경로를 계산하십시오. 해당 경로를 구성하는 노선을 소유한 모든 플레이어는 5점을 얻습니다.
(참고: 점수가 20점 이상이 될 경우엔 20 옆에 자신의 터널 패를 놓아 20점을 표시하고 나머지 점수 위에 점수 패를 올리십시오. 점수가 0점 미만이 될 경우엔 0 옆에 자신의 터널 패를 놓아 음수를 표시하십시오.)
== 승리자 ==
점수를 가장 많이 얻은 플레이어가 도시철도의 왕관을 쓰게 됩니다.
만약 최고점을 얻은 플레이어가 여러 명이라면, 완공된 노선을 가장 많이 소유한 플레이어가 승자가 됩니다. 그것도 같다면, 터널을 가장 많이 놓은 플레이어가 승리합니다. 만약 그것마저도 같다면, 민사 소송을 제기해서 승자를 가리는 방법밖에 없습니다.
== 특별 규칙 ==
플레이어가 2명인 경우: 3개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
시험 운행에 대한 특별 규칙은 보드게임 아레나에는 이식되지 않았습니다.
플레이어가 3명인 경우: 4개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
== 변형 규칙 ==
'''부패한 지방자치'''(3~4 플레이어)
각 플레이어는 목적지 패를 글자가 쓰인 면이 아래로 가도록 감춰 놓습니다. 목적지 패는 도시의 목적지 위치에 놓일 때 공개됩니다.
'''부패는 없다'''(3~4 플레이어)
플레이어는 다음과 같이 미리 설정된 목적지 패를 가져갑니다. 모든 것이 확실하고 분명합니다.
플레이어가 4명인 경우
:플레이어 1: 주거 A, 상업 B, 유흥 C
:플레이어 2: 주거 D, 상업 A, 유흥 E
:플레이어 3: 주거 F, 상업 E, 유흥 B
:플레이어 4: 주거 C, 상업 D, 유흥 F
플레이어가 3명인 경우
:플레이어 1: 주거 A & D, 상업 B, 유흥 C
:플레이어 2: 주거 C, 상업 A & E, 유흥 F
:플레이어 3: 주거 F, 상업 D, 유흥 B & E
메트로매니아 공식 룰북, Spiel ou Face
e7479268cb1db68b31d4e8513f09f5facde58994
1214
1213
2016-10-11T06:33:27Z
Prethousand flower
6335
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
Take advantage of other players lines (for example, stations
are built wherever two lines meet ; you can win points at the
end by sharing the quickest trip), and try also to deroute or
even block off your opponents at the right time, to keep them
from well completing their lines!
At the end of the game, the city government will run seven
"test trips" between designated destinations, placed by the
players themselves during the game.
For each test trip, the fastest connection between the two
points will be rewarded with Public Utility Points, and the
player whose subways have the most points wins!
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 가져갑니다.
'''점수 패'''(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 '''터널 패'''를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 '''시작 지점 패'''(흰색 화살표)와 '''종착 지점 패'''(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 '''목적지 패'''(Destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다. 이 짝을 이룬 2개의 목적지는 시험 운행의 시종착지가 됩니다. 시험 운행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝을 이루는 패가 요약되어 있습니다.
마지막으로, 30개의 '''역 패'''(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 가져가지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''목적지 패 분배'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
게임은 가장 "도시적인"(urbane) 플레이어부터 시작하며 턴은 그로부터 시계방향으로 주어집니다.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
:- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
:- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 육각형인 도시의 6개의 변 중 첫 번째 노선이 시작한 변과 그에 인접한 2개의 변에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
:- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
:- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
:- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
:- 터널을 파는 턴에서는 반드시 3개의 터널을 건설해야 합니다. 단, 터널을 건설할 수 있는 공간이 그보다 적을 경우에는 예외입니다. 반드시 3개의 터널을 한 노선에 지을 필요는 없으며 두 개의 노선에 지은 터널의 갯수의 합이 3개여도 가능합니다.
'''특별 구역'''
도시 가장자리의 (화살표가 있는) 시작 지점과 종착 지점에는 노선의 시작이나 끝이 되는 터널 패만 올릴 수 있으며 그 외의 용도로는 사용할 수 없습니다.
공원과 호수 위에는 터널 패를 놓을 수 없습니다.
목적지가 그려진 위치에 터널 패를 놓은 후에 바로 그 위에 자신의 목적지 패를 글자가 쓰여 있는 부분이 위로 오도록 놓습니다. 물론 지도의 목적지와 목적지 패의 목적지는 같은 종류여야 합니다.
만약 같은 종류의 목적지 패가 없다면, 그 목적지 위치에는 터널을 건설할 수 없습니다.
또한, 각 플레이어는 한 턴에 목적지 패를 한 개만 올려놓을 수 있고, 지도상에서 다른 종류의 목적지끼리 꼭짓점 또는 변이 접할 때 그 두 목적지에 서로 같은 글자가 쓰여진 목적지 패를 놓을 수 없습니다.
'''환승역'''
다음과 같은 경우엔 역이 자동으로 만들어집니다:
:- 노선이 다른 노선과 교차할 때, 두 노선이 만나는 지점에 역 패를 놓습니다.
:- 노선이 다른 노선과 나란히 가다 갈라질 때, 갈라지는 지점에 역 패를 놓습니다. 단, 나란히 놓인 두 노선이 위치만 바뀌는 경우에는 놓지 않습니다.
자신의 노선 위의 역이 지도의 목적지가 그려진 삼각형의 꼭짓점에 놓일 때, 그런 목적지의 갯수만큼 1점을 얻습니다.
'''보통역'''
터널을 파는 대신에, 플레이어는 한 턴에 한 개의 역을 건설할 수 있습니다. 자동으로 건설된 역과 점수 계산의 차이는 없습니다.
'''노선 완공하기'''
노선은 검은 화살표가 있는 공간에서 끝납니다. 노선은 도시의 변 6개 중 그 노선이 시작한 변과 그 양 옆의 두 변에서는 끝날 수 없습니다. 단, 나머지 세 변의 종착 지점이 모두 선점되어 갈 곳이 없는 경우에는 예외입니다.
노선이 완공될 때, 완공한 플레이어는 즉시 그 노선의 아무 곳에나 보통역을 하나 건설할 수 있습니다. 그러나 그 이후에 그 노선에는 보통역을 건설할 수 없습니다.
'''건설 페이즈의 종료'''
다음 중 한 조건을 만족할 때까지 노선을 건설할 수 있습니다:
:- 한 플레이어가 2개의 노선을 모두 완공했을 때
:- 모든 역 패가 사용되었을 때
:- 완공된 노선과 더이상 완공될 수 없는 노선이 합해서 5개 이상일 때(완공될 수 없는 노선이란 해당 노선이 뻗어나갈 수 있는 지점이 모두 선점되었거나 터널 패를 놓을 수 없는 공간(공원·호수)인 경우, 또는 그 노선의 모든 터널 패가 사용된 경우를 말하며, 이 이유로 건설 페이즈가 종료될 때는 다른 모든 플레이어에게 한 턴을 더 준 후에 종료합니다.)
이후 점수를 계산합니다.
== 점수 계산 ==
'''노선 점수'''
플레이어가 건설한 노선에 따른 점수는 다음과 같이 계산합니다:
:- 자신의 노선 2개를 모두 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 온전히 가져갑니다.
:- 자신의 노선을 한 개만 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 반만 가져갑니다.
:- 자신의 노선을 한 개도 완공하지 못한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 모두 잃습니다.
이 기준에 따라 점수 패를 이동하십시오.
'''시험 운행 점수'''
같은 글자가 쓰인 목적지 패 간에 시험 운행이 시행됩니다. 각 운행에서 가장 적은 시간이 소요되는 경로를 계산합니다.
:- 운행은 한 역에서 다음 역까지 가는 데 1분이 소요됩니다. (그 사이에 몇 개의 터널 패가 있는지는 상관없습니다)
:- 다른 노선으로 갈아타는 데는 3분이 소요됩니다.
가장 적은 시간이 소요되는 경로를 구성하는 노선을 소유하고 있는 모든 플레이어는 3점씩 받고, 시험 운행의 시종착점인 목적지 패를 놓은 플레이어는 3점씩을 더 받습니다.
가장 적은 시간이 소요되는 경로가 여러 개일 수도 있습니다. 한 플레이어의 노선이 여러 개의 경로에 모두 관여하고 있더라도 한 시험 운행 구간에서 플레이어는 한 번만 점수를 얻을 수 있습니다.
가장 적은 시간이 소요되는 경로에 자신의 노선이 없는 플레이어는 점수를 얻을 수 없습니다.
'''운행 불가능'''
노선의 건설 상황에 따라 시험 운행이 불가능할 경우도 있습니다.
이런 경우엔, 도시에서 조사 위원회를 구성해 그 책임이 있는 플레이어(들)에게 벌점을 부과합니다.
:- 목적지 패가 보드 위에 놓이지 않았다면, 그 목적지 패를 놓지 못한 플레이어에게 책임이 있습니다.
:- 목적지 패가 놓여졌지만 그 위에 역이 지어지지 않았다면, 역이 지어지지 못한 목적지 패를 놓은 플레이어에게 책임이 있습니다.
:- 두 목적지 패가 모두 놓여졌지만 둘을 연결하는 경로가 존재하지 않는다면, 그 두 목적지 패를 놓은 플레이어에게 책임이 있습니다.
책임이 있는 플레이어(들)은 6점을 잃습니다.
'''시험 운행 결승'''
마지막 시험 운행은 공원과 호수 사이에서 시행됩니다. 마찬가지로 가장 적은 시간이 소요되는 경로를 계산하십시오. 해당 경로를 구성하는 노선을 소유한 모든 플레이어는 5점을 얻습니다.
(참고: 점수가 20점 이상이 될 경우엔 20 옆에 자신의 터널 패를 놓아 20점을 표시하고 나머지 점수 위에 점수 패를 올리십시오. 점수가 0점 미만이 될 경우엔 0 옆에 자신의 터널 패를 놓아 음수를 표시하십시오.)
== 승리자 ==
점수를 가장 많이 얻은 플레이어가 도시철도의 왕관을 쓰게 됩니다.
만약 최고점을 얻은 플레이어가 여러 명이라면, 완공된 노선을 가장 많이 소유한 플레이어가 승자가 됩니다. 그것도 같다면, 터널을 가장 많이 놓은 플레이어가 승리합니다. 만약 그것마저도 같다면, 민사 소송을 제기해서 승자를 가리는 방법밖에 없습니다.
== 특별 규칙 ==
플레이어가 2명인 경우: 3개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
시험 운행에 대한 특별 규칙은 보드게임 아레나에는 이식되지 않았습니다.
플레이어가 3명인 경우: 4개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
== 변형 규칙 ==
'''부패한 지방자치'''(3~4 플레이어)
각 플레이어는 목적지 패를 글자가 쓰인 면이 아래로 가도록 감춰 놓습니다. 목적지 패는 도시의 목적지 위치에 놓일 때 공개됩니다.
'''부패는 없다'''(3~4 플레이어)
플레이어는 다음과 같이 미리 설정된 목적지 패를 가져갑니다. 모든 것이 확실하고 분명합니다.
플레이어가 4명인 경우
:플레이어 1: 주거 A, 상업 B, 유흥 C
:플레이어 2: 주거 D, 상업 A, 유흥 E
:플레이어 3: 주거 F, 상업 E, 유흥 B
:플레이어 4: 주거 C, 상업 D, 유흥 F
플레이어가 3명인 경우
:플레이어 1: 주거 A & D, 상업 B, 유흥 C
:플레이어 2: 주거 C, 상업 A & E, 유흥 F
:플레이어 3: 주거 F, 상업 D, 유흥 B & E
메트로매니아 공식 룰북, Spiel ou Face
4e49ed44a03241c0d104aff21eb6caf6a3d5c8e3
1215
1214
2016-10-11T06:43:21Z
Prethousand flower
6335
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
Take advantage of other players lines (for example, stations
are built wherever two lines meet ; you can win points at the
end by sharing the quickest trip), and try also to deroute or
even block off your opponents at the right time, to keep them
from well completing their lines!
At the end of the game, the city government will run seven
"test trips" between designated destinations, placed by the
players themselves during the game.
For each test trip, the fastest connection between the two
points will be rewarded with Public Utility Points, and the
player whose subways have the most points wins!
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 가져갑니다.
'''점수 패'''(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 '''터널 패'''를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 '''시작 지점 패'''(흰색 화살표)와 '''종착 지점 패'''(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 '''목적지 패'''(Destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다. 이 짝을 이룬 2개의 목적지는 시험 여행의 시종착점이 됩니다. 시험 여행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝을 이루는 패가 요약되어 있습니다.
마지막으로, 30개의 '''역 패'''(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 가져가지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''목적지 패 분배'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
게임은 가장 "도시적인"(urbane) 플레이어부터 시작하며 턴은 그로부터 시계방향으로 주어집니다.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
:- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
:- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 육각형인 도시의 6개의 변 중 첫 번째 노선이 시작한 변과 그에 인접한 2개의 변에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
:- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
:- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
:- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
:- 터널을 파는 턴에서는 반드시 3개의 터널을 건설해야 합니다. 단, 터널을 건설할 수 있는 공간이 그보다 적을 경우에는 예외입니다. 반드시 3개의 터널을 한 노선에 지을 필요는 없으며 두 개의 노선에 지은 터널의 갯수의 합이 3개여도 가능합니다.
'''특별 구역'''
도시 가장자리의 (화살표가 있는) 시작 지점과 종착 지점에는 노선의 시작이나 끝이 되는 터널 패만 올릴 수 있으며 그 외의 용도로는 사용할 수 없습니다.
공원과 호수 위에는 터널 패를 놓을 수 없습니다.
목적지가 그려진 위치에 터널 패를 놓은 후에 바로 그 위에 자신의 목적지 패를 글자가 쓰여 있는 부분이 위로 오도록 놓습니다. 물론 지도에 그려진 목적지와 목적지 패에 그려진 목적지는 같은 종류여야 합니다.
만약 같은 종류의 목적지 패가 없다면, 그 목적지 위치에는 터널을 건설할 수 없습니다.
또한, 각 플레이어는 한 턴에 목적지 패를 한 개만 올려놓을 수 있고, 지도상에서 다른 종류의 목적지가 서로 인접하여 꼭짓점 또는 변이 겹칠 때 그 두 목적지에 서로 같은 글자가 쓰여진 목적지 패를 놓을 수 없습니다.
'''환승역'''
다음과 같은 경우엔 역이 자동으로 만들어집니다:
:- 노선이 다른 노선과 교차할 때, 두 노선이 만나는 지점에 역 패를 놓습니다.
:- 노선이 다른 노선과 나란히 가다 갈라질 때, 갈라지는 지점에 역 패를 놓습니다. 단, 나란히 놓인 두 노선이 위치만 바뀌는 경우에는 놓지 않습니다.
자신의 노선 위의 역이 지도에서 목적지가 그려진 삼각형의 꼭짓점에 놓일 때, 그런 목적지의 갯수만큼 1점을 얻습니다.
'''보통역'''
터널을 파는 대신에, 플레이어는 한 턴에 한 개의 역을 건설할 수 있습니다. 자동으로 건설된 역과 점수 계산의 차이는 없습니다.
'''노선 완공하기'''
노선은 검은 화살표가 있는 공간에서 끝납니다. 노선은 도시의 변 6개 중 그 노선이 시작한 변과 그 양 옆의 두 변에서는 끝날 수 없습니다. 단, 나머지 세 변의 종착 지점이 모두 선점되어 갈 곳이 없는 경우에는 예외입니다.
노선이 완공될 때, 완공한 플레이어는 즉시 그 노선의 아무 곳에나 보통역을 하나 건설할 수 있습니다. 그러나 그 이후에 그 노선에는 보통역을 건설할 수 없습니다.
'''건설 페이즈의 종료'''
다음 중 한 조건을 만족할 때까지 노선을 건설할 수 있습니다:
:- 한 플레이어가 2개의 노선을 모두 완공했을 때
:- 모든 역 패가 사용되었을 때
:- 완공된 노선과 더이상 완공될 수 없는 노선이 합해서 5개 이상일 때(완공될 수 없는 노선이란 해당 노선이 뻗어나갈 수 있는 지점이 모두 선점되었거나 터널 패를 놓을 수 없는 공간(공원·호수)인 경우, 또는 그 노선의 모든 터널 패가 사용된 경우를 말하며, 이 이유로 건설 페이즈가 종료될 때는 다른 모든 플레이어에게 한 턴을 더 준 후에 종료합니다.)
이후 점수를 계산합니다.
== 점수 계산 ==
'''노선 점수'''
플레이어가 건설한 노선에 따른 점수는 다음과 같이 계산합니다:
:- 자신의 노선 2개를 모두 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 온전히 가져갑니다.
:- 자신의 노선을 한 개만 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 반만 가져갑니다.
:- 자신의 노선을 한 개도 완공하지 못한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 모두 잃습니다.
이 기준에 따라 점수 패를 이동하십시오.
'''시험 이동 점수'''
같은 글자가 쓰인 목적지 패 간에 시험 여행이 시행됩니다. 각 여행에서 가장 적은 시간이 소요되는 경로를 계산합니다.
:- 여행은 한 역에서 다음 역까지 가는 데 1분이 소요됩니다. (그 사이에 몇 개의 터널 패가 있는지는 상관없습니다)
:- 다른 노선으로 갈아타는 데는 3분이 소요됩니다.
가장 적은 시간이 소요되는 경로를 구성하는 노선을 소유하고 있는 모든 플레이어는 3점씩 받고, 시험 여행의 시종착점인 목적지 패를 놓은 플레이어는 3점씩을 더 받습니다.
가장 적은 시간이 소요되는 경로가 여러 개일 수도 있습니다. 한 플레이어의 노선이 여러 개의 경로에 모두 관여하고 있더라도 한 시험 여행 구간에서 플레이어는 한 번만 점수를 얻을 수 있습니다.
가장 적은 시간이 소요되는 경로에 자신의 노선이 없는 플레이어는 점수를 얻을 수 없습니다.
'''여행 불가능'''
노선의 건설 상황에 따라 시험 여행이 불가능할 경우도 있습니다.
이런 경우엔, 도시에서 조사 위원회를 구성해 그 책임이 있는 플레이어(들)에게 벌점을 부과합니다.
:- 목적지 패가 보드 위에 놓이지 않았다면, 그 목적지 패를 놓지 못한 플레이어에게 책임이 있습니다.
:- 목적지 패가 놓여졌지만 그 위에 역이 지어지지 않았다면, 역이 지어지지 못한 목적지 패를 놓은 플레이어에게 책임이 있습니다.
:- 두 목적지 패가 모두 놓여졌지만 둘을 연결하는 경로가 존재하지 않는다면, 그 두 목적지 패를 놓은 플레이어에게 책임이 있습니다.
책임이 있는 플레이어(들)은 6점을 잃습니다.
'''결승 시험'''
마지막 시험 여행은 공원과 호수 사이에서 시행됩니다. 마찬가지로 가장 적은 시간이 소요되는 경로를 계산하십시오. 해당 경로를 구성하는 노선을 소유한 모든 플레이어는 5점을 얻습니다.
(참고: 점수가 20점 이상이 될 경우엔 20 옆에 자신의 터널 패를 놓아 20점을 표시하고 나머지 점수 위에 점수 패를 올리십시오. 점수가 0점 미만이 될 경우엔 0 옆에 자신의 터널 패를 놓아 음수를 표시하십시오.)
== 승리자 ==
점수를 가장 많이 얻은 플레이어가 도시철도의 왕관을 쓰게 됩니다.
만약 최고점을 얻은 플레이어가 여러 명이라면, 완공된 노선을 가장 많이 소유한 플레이어가 승자가 됩니다. 그것도 같다면, 터널을 가장 많이 놓은 플레이어가 승리합니다. 만약 그것마저도 같다면, 민사 소송을 제기해서 승자를 가리는 방법밖에 없습니다.
== 특별 규칙 ==
플레이어가 2명인 경우: 3개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
시험 운행에 대한 특별 규칙은 보드게임 아레나에는 이식되지 않았습니다.
플레이어가 3명인 경우: 4개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
== 변형 규칙 ==
'''부패한 지방자치'''(3~4 플레이어)
각 플레이어는 목적지 패를 글자가 쓰인 면이 아래로 가도록 감춰 놓습니다. 목적지 패는 도시의 목적지 위치에 놓일 때 공개됩니다.
'''부패는 없다'''(3~4 플레이어)
플레이어는 다음과 같이 미리 설정된 목적지 패를 가져갑니다. 모든 것이 확실하고 분명합니다.
플레이어가 4명인 경우
:플레이어 1: 주거 A, 상업 B, 유흥 C
:플레이어 2: 주거 D, 상업 A, 유흥 E
:플레이어 3: 주거 F, 상업 E, 유흥 B
:플레이어 4: 주거 C, 상업 D, 유흥 F
플레이어가 3명인 경우
:플레이어 1: 주거 A & D, 상업 B, 유흥 C
:플레이어 2: 주거 C, 상업 A & E, 유흥 F
:플레이어 3: 주거 F, 상업 D, 유흥 B & E
메트로매니아 공식 룰북, Spiel ou Face
fcc132c5fb001f78ecbeb0ca2277847f07f60cec
1216
1215
2016-10-11T06:56:05Z
Prethousand flower
6335
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
플레이어들은 가장 빠른 여행에 자신의 노선을 제공함으로써 점수를 얻을 수 있습니다. 다른 경쟁자들의 노선보다 더 빠른 경로를 건설하거나 그들의 노선을 봉쇄해 경쟁에서 승리하십시오. 건설이 끝나면 시 당국은 지정된 지역 사이의 시험 여행을 시행해 여러분의 노선을 평가할 것입니다. 그리고 시험 여행에 사용되는 지역은 플레이어들이 게임 중에 놓은 목적지에 따라 결정됩니다. 가장 많은 공공 사업 점수를 얻어 게임에서 승리하십시오.
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 가져갑니다.
'''점수 패'''(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 '''터널 패'''를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 '''시작 지점 패'''(흰색 화살표)와 '''종착 지점 패'''(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 '''목적지 패'''(Destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다. 이 짝을 이룬 2개의 목적지는 시험 여행의 시종착점이 됩니다. 시험 여행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝을 이루는 패가 요약되어 있습니다.
마지막으로, 30개의 '''역 패'''(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 가져가지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''목적지 패 분배'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
게임은 가장 "도시적인"(urbane) 플레이어부터 시작하며 턴은 그로부터 시계방향으로 주어집니다.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
:- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
:- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 육각형인 도시의 6개의 변 중 첫 번째 노선이 시작한 변과 그에 인접한 2개의 변에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
:- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
:- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
:- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
:- 터널을 파는 턴에서는 반드시 3개의 터널을 건설해야 합니다. 단, 터널을 건설할 수 있는 공간이 그보다 적을 경우에는 예외입니다. 반드시 3개의 터널을 한 노선에 지을 필요는 없으며 두 개의 노선에 지은 터널의 갯수의 합이 3개여도 가능합니다.
'''특별 구역'''
도시 가장자리의 (화살표가 있는) 시작 지점과 종착 지점에는 노선의 시작이나 끝이 되는 터널 패만 올릴 수 있으며 그 외의 용도로는 사용할 수 없습니다.
공원과 호수 위에는 터널 패를 놓을 수 없습니다.
목적지가 그려진 위치에 터널 패를 놓은 후에 바로 그 위에 자신의 목적지 패를 글자가 쓰여 있는 부분이 위로 오도록 놓습니다. 물론 지도에 그려진 목적지와 목적지 패에 그려진 목적지는 같은 종류여야 합니다.
만약 같은 종류의 목적지 패가 없다면, 그 목적지 위치에는 터널을 건설할 수 없습니다.
또한, 각 플레이어는 한 턴에 목적지 패를 한 개만 올려놓을 수 있고, 지도상에서 다른 종류의 목적지가 서로 인접하여 꼭짓점 또는 변이 겹칠 때 그 두 목적지에 서로 같은 글자가 쓰여진 목적지 패를 놓을 수 없습니다.
'''환승역'''
다음과 같은 경우엔 역이 자동으로 만들어집니다:
:- 노선이 다른 노선과 교차할 때, 두 노선이 만나는 지점에 역 패를 놓습니다.
:- 노선이 다른 노선과 나란히 가다 갈라질 때, 갈라지는 지점에 역 패를 놓습니다. 단, 나란히 놓인 두 노선이 위치만 바뀌는 경우에는 놓지 않습니다.
자신의 노선 위의 역이 지도에서 목적지가 그려진 삼각형의 꼭짓점에 놓일 때, 그런 목적지의 갯수만큼 1점을 얻습니다.
'''보통역'''
터널을 파는 대신에, 플레이어는 한 턴에 한 개의 역을 건설할 수 있습니다. 자동으로 건설된 역과 점수 계산의 차이는 없습니다.
'''노선 완공하기'''
노선은 검은 화살표가 있는 공간에서 끝납니다. 노선은 도시의 변 6개 중 그 노선이 시작한 변과 그 양 옆의 두 변에서는 끝날 수 없습니다. 단, 나머지 세 변의 종착 지점이 모두 선점되어 갈 곳이 없는 경우에는 예외입니다.
노선이 완공될 때, 완공한 플레이어는 즉시 그 노선의 아무 곳에나 보통역을 하나 건설할 수 있습니다. 그러나 그 이후에 그 노선에는 보통역을 건설할 수 없습니다.
'''건설 페이즈의 종료'''
다음 중 한 조건을 만족할 때까지 노선을 건설할 수 있습니다:
:- 한 플레이어가 2개의 노선을 모두 완공했을 때
:- 모든 역 패가 사용되었을 때
:- 완공된 노선과 더이상 완공될 수 없는 노선이 합해서 5개 이상일 때(완공될 수 없는 노선이란 해당 노선이 뻗어나갈 수 있는 지점이 모두 선점되었거나 터널 패를 놓을 수 없는 공간(공원·호수)인 경우, 또는 그 노선의 모든 터널 패가 사용된 경우를 말하며, 이 이유로 건설 페이즈가 종료될 때는 다른 모든 플레이어에게 한 턴을 더 준 후에 종료합니다.)
이후 점수를 계산합니다.
== 점수 계산 ==
'''노선 점수'''
플레이어가 건설한 노선에 따른 점수는 다음과 같이 계산합니다:
:- 자신의 노선 2개를 모두 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 온전히 가져갑니다.
:- 자신의 노선을 한 개만 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 반만 가져갑니다.
:- 자신의 노선을 한 개도 완공하지 못한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 모두 잃습니다.
이 기준에 따라 점수 패를 이동하십시오.
'''시험 이동 점수'''
같은 글자가 쓰인 목적지 패 간에 시험 여행이 시행됩니다. 다음 기준에 따라 각 여행에서 가장 빠른(가장 적은 시간이 소요되는) 경로를 계산합니다:
:- 여행은 한 역에서 다음 역까지 가는 데 1분이 소요됩니다. (그 사이에 몇 개의 터널 패가 있는지는 상관없습니다)
:- 다른 노선으로 갈아타는 데는 3분이 소요됩니다.
가장 빠른 노선을 소유하고 있는 모든 플레이어는 3점씩 받고, 시험 여행의 시종착점인 목적지 패를 놓은 플레이어는 3점씩을 더 받습니다.
가장 빠른 경로가 여러 개일 수도 있습니다. 한 플레이어의 노선이 그 여러 개의 경로에 모두 관여하고 있더라도 한 시험 여행 구간에서 플레이어는 한 번만 점수를 얻을 수 있습니다.
가장 빠른 경로에 자신의 노선이 없는 플레이어는 점수를 얻을 수 없습니다.
'''여행 불가능'''
노선의 건설 상황에 따라 시험 여행이 불가능할 경우도 있습니다.
이런 경우엔, 도시에서 조사 위원회를 구성해 그 책임이 있는 플레이어(들)에게 벌점을 부과합니다.
:- 목적지 패가 보드 위에 놓이지 않았다면, 그 목적지 패를 놓지 못한 플레이어에게 책임이 있습니다.
:- 목적지 패가 놓여졌지만 그 위에 역이 지어지지 않았다면, 역이 지어지지 못한 목적지 패를 놓은 플레이어에게 책임이 있습니다.
:- 두 목적지 패가 모두 놓여졌지만 둘을 연결하는 경로가 존재하지 않는다면, 그 두 목적지 패를 놓은 플레이어들에게 책임이 있습니다.
책임이 있는 플레이어(들)은 6점을 잃습니다.
'''결승 시험'''
마지막 시험 여행은 공원과 호수 사이에서 시행됩니다. 마찬가지로 가장 적은 시간이 소요되는 경로를 계산하십시오. 해당 경로를 구성하는 노선을 소유한 모든 플레이어는 5점을 얻습니다.
(참고: 점수가 20점 이상이 될 경우엔 20 옆에 자신의 터널 패를 놓아 20점을 표시하고 나머지 점수 위에 점수 패를 올리십시오. 점수가 0점 미만이 될 경우엔 0 옆에 자신의 터널 패를 놓아 음수를 표시하십시오.)
== 승리자 ==
점수를 가장 많이 얻은 플레이어가 도시철도의 왕관을 쓰게 됩니다.
만약 최고점을 얻은 플레이어가 여러 명이라면, 완공된 노선을 가장 많이 소유한 플레이어가 승자가 됩니다. 그것도 같다면, 터널을 가장 많이 놓은 플레이어가 승리합니다. 만약 그것마저도 같다면, 민사 소송을 제기해서 승자를 가리는 방법밖에 없습니다.
== 특별 규칙 ==
플레이어가 2명인 경우: 3개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
시험 운행에 대한 특별 규칙은 보드게임 아레나에는 이식되지 않았습니다.
플레이어가 3명인 경우: 4개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
== 변형 규칙 ==
'''부패한 지방자치'''(3~4 플레이어)
각 플레이어는 목적지 패를 글자가 쓰인 면이 아래로 가도록 감춰 놓습니다. 목적지 패는 도시의 목적지 위치에 놓일 때 공개됩니다.
'''부패는 없다'''(3~4 플레이어)
플레이어는 다음과 같이 미리 설정된 목적지 패를 가져갑니다. 모든 것이 확실하고 분명합니다.
플레이어가 4명인 경우
:플레이어 1: 주거 A, 상업 B, 유흥 C
:플레이어 2: 주거 D, 상업 A, 유흥 E
:플레이어 3: 주거 F, 상업 E, 유흥 B
:플레이어 4: 주거 C, 상업 D, 유흥 F
플레이어가 3명인 경우
:플레이어 1: 주거 A & D, 상업 B, 유흥 C
:플레이어 2: 주거 C, 상업 A & E, 유흥 F
:플레이어 3: 주거 F, 상업 D, 유흥 B & E
메트로매니아 공식 룰북, Spiel ou Face
50243abbca029ef4fc4a50fe578b53cd324b6c81
Gamehelpmetromaniab
0
174
1217
2016-10-11T06:59:08Z
Prethousand flower
6335
새 문서: == 개요와 목표 == 메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다. ...
wikitext
text/x-wiki
== 개요와 목표 ==
메트로매니아 게임에서 플레이어들은 도시철도 건설 회사가 되어 도시를 지나는 2개의 지하철 노선을 건설해야 합니다.
여러분의 목표는 주거(residential) 지역, 상업(commercial) 지역, 그리고 유흥(entertainment) 지역과 같은 중요한 지역들을 연결하고, 역을 제공하는 것입니다.
플레이어들은 가장 빠른 여행에 자신의 노선을 제공함으로써 점수를 얻을 수 있습니다. 다른 경쟁자들의 노선보다 더 빠른 경로를 건설하거나 그들의 노선을 봉쇄해 경쟁에서 승리하십시오. 건설이 끝나면 시 당국은 지정된 지역 사이의 시험 여행을 시행해 여러분의 노선을 평가할 것입니다. 그리고 시험 여행에 사용되는 지역은 플레이어들이 게임 중에 놓은 목적지에 따라 결정됩니다. 가장 많은 공공 사업 점수를 얻어 게임에서 승리하십시오.
== 게임 구성물과 준비 방법 ==
'''게임 보드'''
4조각으로 나눠진 보드의 틀 조각을 맞춘 후, 그 안에 6개의 큰 삼각형으로 된 도시 조각을 무작위로 섞어 맞추면 보드가 준비됩니다.
'''기물'''
플레이어는 각각 자기 색깔의 패를 가져갑니다.
'''점수 패'''(score marker)를 점수 궤도(scoring track)의 "0" 위치에 놓으십시오. 열차가 그려져 있는 이 패는 플레이어의 점수를 표시합니다.
자신의 색깔에 맞는 '''터널 패'''를 가져가십시오. 터널 패는 실선으로 된(solid) 패와 점선으로 된(striped) 패가 있으며 각각 하나의 노선을 표시합니다.
각 노선에는 '''시작 지점 패'''(흰색 화살표)와 '''종착 지점 패'''(검은색 화살표), 그리고 18개의 터널 패가 있어야 합니다.
또한 12개의 '''목적지 패'''(destination marker)가 있습니다. 여기에는 A에서 F까지의 글자가 써 있어서 다른 목적지 패와 함께 패 2개의 짝을 이룹니다. 이 짝을 이룬 2개의 목적지는 시험 여행의 시종착점이 됩니다. 시험 여행은 건설 페이즈가 종료된 이후 시행되며, 보드의 오른쪽 위에 짝을 이루는 패가 요약되어 있습니다.
마지막으로, 30개의 '''역 패'''(station marker)를 보드의 옆에 놓으십시오. 이 패는 어느 플레이어도 가져가지 않습니다.
도시는 삼각형 블록들로 구성됩니다. 블록들은 비었거나, 목적지 표시가 되어 있거나, 호수 또는 공원입니다. 도시의 가장자리에는 노선이 시작하는 지점을 의미하는 흰색 화살표와 노선이 끝나는 지점을 의미하는 검은 색 화살표를 놓습니다.
== 게임의 흐름 ==
'''목적지 패 분배'''
목적지 패를 종류별로 모아 글자가 있는 면이 보이지 않게 뒤집은 후 잘 섞습니다.
플레이어가 4명인 경우, 각 플레이어는 각 종류(주거 지역, 상업 지역, 유흥 지역)의 목적지 패를 하나씩 무작위로 가져갑니다.
그 후 플레이어는 자신의 목적지 패를 자신만 확인합니다. 만약 자신의 패 중 쓰여 있는 글자가 겹치는 패가 있다면 3개의 패에 각각 다른 글자가 쓰여 있을 때까지 겹치는 패 중 하나를 버리고 새 패를 가져와야 합니다.
모든 플레이어가 목적지 패를 확정했다면, 자신의 목적지 패를 뒤집어 다른 플레이어들에게 글자가 보이도록 놓습니다.
플레이어가 3명인 경우, 각 플레이어들은 한 개의 목적지 패를 더 가져갑니다.
플레이어가 2명인 경우, 각 플레이어는 6개의 목적지 패를 가져갑니다. 즉 한 플레이어가 보드의 오른쪽 위에 있는 목적지 패 요약표에서 왼쪽에 있는 6개의 패를 가져가면, 다른 플레이어가 오른쪽에 있는 6개의 패를 가져가면 됩니다.
'''플레이어 턴'''
게임은 가장 "도시적인"(urbane) 플레이어부터 시작하며 턴은 그로부터 시계방향으로 주어집니다.
플레이어는 한 턴에서 다음 행동들 중 '''반드시''' 하나를 선택하여 해야 합니다:
:- 3개의 터널 파기(터널은 반드시 이미 놓여 있는 자신의 노선에서 이어져야 합니다)
:- 보통역(intermediate station) 건설하기(자신의 노선 위에 있어야 합니다)
'''노선 시작하기'''
각 플레이어는 2개의 노선을 건설합니다.
자신의 첫 차례에 플레이어는 노선 한 개의 건설을 시작합니다.
노선은 도시의 가장자리에 있는 흰색 화살표에서 시작합니다.
자기 색깔의 시작 지점 패를 흰색 화살표 위에 놓아 노선 건설을 시작합니다.
자신의 다음 차례부터 두 번째 노선의 건설을 시작할 수 있지만, 두 번째 노선은 육각형인 도시의 6개의 변 중 첫 번째 노선이 시작한 변과 그에 인접한 2개의 변에서는 시작할 수 없습니다.
'''터널 파기'''
도시의 빈 삼각형 공간에 터널 패를 놓아 노선을 건설합니다. 한 삼각형에는 하나의 터널 패만 놓을 수 있습니다.
또한 터널을 지을 때는 다음과 같은 규칙을 지켜야 합니다:
:- 노선은 마지막 지어진 부분부터 계속 이어야 합니다. 즉 한 노선이 분기할 수 없습니다.
:- 노선은 예각으로 꺾일 수 없습니다. 단, 꺾이는 지점에 역이 있을 경우에는 허용됩니다.
:- 한 노선은 순환선을 만들거나 왔던 길을 되돌아갈 수 없습니다.
:- 터널을 파는 턴에서는 반드시 3개의 터널을 건설해야 합니다. 단, 터널을 건설할 수 있는 공간이 그보다 적을 경우에는 예외입니다. 반드시 3개의 터널을 한 노선에 지을 필요는 없으며 두 개의 노선에 지은 터널의 갯수의 합이 3개여도 가능합니다.
'''특별 구역'''
도시 가장자리의 (화살표가 있는) 시작 지점과 종착 지점에는 노선의 시작이나 끝이 되는 터널 패만 올릴 수 있으며 그 외의 용도로는 사용할 수 없습니다.
공원과 호수 위에는 터널 패를 놓을 수 없습니다.
목적지가 그려진 위치에 터널 패를 놓은 후에 바로 그 위에 자신의 목적지 패를 글자가 쓰여 있는 부분이 위로 오도록 놓습니다. 물론 지도에 그려진 목적지와 목적지 패에 그려진 목적지는 같은 종류여야 합니다.
만약 같은 종류의 목적지 패가 없다면, 그 목적지 위치에는 터널을 건설할 수 없습니다.
또한, 각 플레이어는 한 턴에 목적지 패를 한 개만 올려놓을 수 있고, 지도상에서 다른 종류의 목적지가 서로 인접하여 꼭짓점 또는 변이 겹칠 때 그 두 목적지에 서로 같은 글자가 쓰여진 목적지 패를 놓을 수 없습니다.
'''환승역'''
다음과 같은 경우엔 역이 자동으로 만들어집니다:
:- 노선이 다른 노선과 교차할 때, 두 노선이 만나는 지점에 역 패를 놓습니다.
:- 노선이 다른 노선과 나란히 가다 갈라질 때, 갈라지는 지점에 역 패를 놓습니다. 단, 나란히 놓인 두 노선이 위치만 바뀌는 경우에는 놓지 않습니다.
자신의 노선 위의 역이 지도에서 목적지가 그려진 삼각형의 꼭짓점에 놓일 때, 그런 목적지의 갯수만큼 1점을 얻습니다.
'''보통역'''
터널을 파는 대신에, 플레이어는 한 턴에 한 개의 역을 건설할 수 있습니다. 자동으로 건설된 역과 점수 계산의 차이는 없습니다.
'''노선 완공하기'''
노선은 검은 화살표가 있는 공간에서 끝납니다. 노선은 도시의 변 6개 중 그 노선이 시작한 변과 그 양 옆의 두 변에서는 끝날 수 없습니다. 단, 나머지 세 변의 종착 지점이 모두 선점되어 갈 곳이 없는 경우에는 예외입니다.
노선이 완공될 때, 완공한 플레이어는 즉시 그 노선의 아무 곳에나 보통역을 하나 건설할 수 있습니다. 그러나 그 이후에 그 노선에는 보통역을 건설할 수 없습니다.
'''건설 페이즈의 종료'''
다음 중 한 조건을 만족할 때까지 노선을 건설할 수 있습니다:
:- 한 플레이어가 2개의 노선을 모두 완공했을 때
:- 모든 역 패가 사용되었을 때
:- 완공된 노선과 더이상 완공될 수 없는 노선이 합해서 5개 이상일 때(완공될 수 없는 노선이란 해당 노선이 뻗어나갈 수 있는 지점이 모두 선점되었거나 터널 패를 놓을 수 없는 공간(공원·호수)인 경우, 또는 그 노선의 모든 터널 패가 사용된 경우를 말하며, 이 이유로 건설 페이즈가 종료될 때는 다른 모든 플레이어에게 한 턴을 더 준 후에 종료합니다.)
이후 점수를 계산합니다.
== 점수 계산 ==
'''노선 점수'''
플레이어가 건설한 노선에 따른 점수는 다음과 같이 계산합니다:
:- 자신의 노선 2개를 모두 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 온전히 가져갑니다.
:- 자신의 노선을 한 개만 완공한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 반만 가져갑니다.
:- 자신의 노선을 한 개도 완공하지 못한 플레이어는 역과 인접한 목적지의 갯수에 따른 점수를 모두 잃습니다.
이 기준에 따라 점수 패를 이동하십시오.
'''시험 이동 점수'''
같은 글자가 쓰인 목적지 패 간에 시험 여행이 시행됩니다. 다음 기준에 따라 각 여행에서 가장 빠른(가장 적은 시간이 소요되는) 경로를 계산합니다:
:- 여행은 한 역에서 다음 역까지 가는 데 1분이 소요됩니다. (그 사이에 몇 개의 터널 패가 있는지는 상관없습니다)
:- 다른 노선으로 갈아타는 데는 3분이 소요됩니다.
가장 빠른 노선을 소유하고 있는 모든 플레이어는 3점씩 받고, 시험 여행의 시종착점인 목적지 패를 놓은 플레이어는 3점씩을 더 받습니다.
가장 빠른 경로가 여러 개일 수도 있습니다. 한 플레이어의 노선이 그 여러 개의 경로에 모두 관여하고 있더라도 한 시험 여행 구간에서 플레이어는 한 번만 점수를 얻을 수 있습니다.
가장 빠른 경로에 자신의 노선이 없는 플레이어는 점수를 얻을 수 없습니다.
'''여행 불가능'''
노선의 건설 상황에 따라 시험 여행이 불가능할 경우도 있습니다.
이런 경우엔, 도시에서 조사 위원회를 구성해 그 책임이 있는 플레이어(들)에게 벌점을 부과합니다.
:- 목적지 패가 보드 위에 놓이지 않았다면, 그 목적지 패를 놓지 못한 플레이어에게 책임이 있습니다.
:- 목적지 패가 놓여졌지만 그 위에 역이 지어지지 않았다면, 역이 지어지지 못한 목적지 패를 놓은 플레이어에게 책임이 있습니다.
:- 두 목적지 패가 모두 놓여졌지만 둘을 연결하는 경로가 존재하지 않는다면, 그 두 목적지 패를 놓은 플레이어들에게 책임이 있습니다.
책임이 있는 플레이어(들)은 6점을 잃습니다.
'''결승 시험'''
마지막 시험 여행은 공원과 호수 사이에서 시행됩니다. 마찬가지로 가장 적은 시간이 소요되는 경로를 계산하십시오. 해당 경로를 구성하는 노선을 소유한 모든 플레이어는 5점을 얻습니다.
(참고: 점수가 20점 이상이 될 경우엔 20 옆에 자신의 터널 패를 놓아 20점을 표시하고 나머지 점수 위에 점수 패를 올리십시오. 점수가 0점 미만이 될 경우엔 0 옆에 자신의 터널 패를 놓아 음수를 표시하십시오.)
== 승리자 ==
점수를 가장 많이 얻은 플레이어가 도시철도의 왕관을 쓰게 됩니다.
만약 최고점을 얻은 플레이어가 여러 명이라면, 완공된 노선을 가장 많이 소유한 플레이어가 승자가 됩니다. 그것도 같다면, 터널을 가장 많이 놓은 플레이어가 승리합니다. 만약 그것마저도 같다면, 민사 소송을 제기해서 승자를 가리는 방법밖에 없습니다.
== 특별 규칙 ==
플레이어가 2명인 경우: 3개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
시험 운행에 대한 특별 규칙은 보드게임 아레나에는 이식되지 않았습니다.
플레이어가 3명인 경우: 4개의 노선이 완공 또는 완공 불가능해질 때 건설 페이즈가 종료됩니다.
== 변형 규칙 ==
'''부패한 지방자치'''(3~4 플레이어)
각 플레이어는 목적지 패를 글자가 쓰인 면이 아래로 가도록 감춰 놓습니다. 목적지 패는 도시의 목적지 위치에 놓일 때 공개됩니다.
'''부패는 없다'''(3~4 플레이어)
플레이어는 다음과 같이 미리 설정된 목적지 패를 가져갑니다. 모든 것이 확실하고 분명합니다.
플레이어가 4명인 경우
:플레이어 1: 주거 A, 상업 B, 유흥 C
:플레이어 2: 주거 D, 상업 A, 유흥 E
:플레이어 3: 주거 F, 상업 E, 유흥 B
:플레이어 4: 주거 C, 상업 D, 유흥 F
플레이어가 3명인 경우
:플레이어 1: 주거 A & D, 상업 B, 유흥 C
:플레이어 2: 주거 C, 상업 A & E, 유흥 F
:플레이어 3: 주거 F, 상업 D, 유흥 B & E
메트로매니아 공식 룰북, Spiel ou Face
a864b6a6a32334fcd41408950e8de10afc4a6ecb
대문
0
175
1219
2016-12-10T14:11:07Z
Yooyou7
6164
영어 위키 제작 시작.
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다.
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpsechsnimmt|6 Nimmt!]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpakeruption|Eruption]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
</td>
<td valign="top">
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoikoi|Koi-koi]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
b1095a418afb15a1aeaa0381ae90a82e3350a434
1220
1219
2016-12-10T14:12:11Z
Yooyou7
6164
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다.--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpsechsnimmt|6 Nimmt!]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpakeruption|Eruption]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
</td>
<td valign="top">
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoikoi|Koi-koi]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
5f77a26d2422dfaba57975eb81dabfabad2b104c
1221
1220
2016-12-10T14:12:43Z
Yooyou7
6164
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpsechsnimmt|6 Nimmt!]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpakeruption|Eruption]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
</td>
<td valign="top">
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoikoi|Koi-koi]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
86dbbb9f3771f2bfbd84278757baa840180b1936
1224
1221
2016-12-10T14:37:51Z
Yooyou7
6164
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcantstop|Can't Stop]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpakeruption|Eruption]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
</td>
<td valign="top">
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoikoi|Koi-koi]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
df00dbdebb1f4ae14cacf8c65d23fd2bf0f0f9cb
1227
1224
2016-12-11T05:04:08Z
Yooyou7
6164
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpakeruption|Eruption]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
</td>
<td valign="top">
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoikoi|Koi-koi]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
fc2a6ccaed34649ec1bbab677f3f08675535f630
1230
1227
2016-12-13T10:43:43Z
Yooyou7
6164
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
</td>
<td valign="top">
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoikoi|Koi-koi]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
4a9c3664d8d208f8c9cfc4f337ba58be0386885d
Gamehelpcantstop
0
35
1226
913
2016-12-11T05:03:55Z
Yooyou7
6164
캔트 스탑 작성. (번역이지만.)
wikitext
text/x-wiki
=캔트 스탑!=
캔트 스탑(Can't Stop, 영어 직역)은 주사위를 통해 안전과 위험 사이에서 운을 시험하는 게임입니다.
==규칙==
캔트 스탑은 2부터 12까지의 11개의 열이 있는 보드와 4개의 주사위, 그리고 말(각 플레이어를 상징하는 색깔 말과, 모두가 공유하는 3개의 검정색 말)로 턴이 진행됩니다.
===턴 진행===
자신의 턴이 되면, 주사위 4개를 굴립니다. 그 뒤 주사위 4개를 적당히 2개씩 나눠서 그 두 눈금의 합에 해당하는 열을 전진시킵니다.
예시 :
* 눈금 3, 3, 4, 4가 나온 경우, (3,3), (4,4)로 나눠서 6과 8을 전진시키거나, (3,4), (3,4)로 나눠서 7을 2칸 전진시킬 수 있습니다.
* 눈금 2, 3, 4, 5가 나온 경우, (2,5), (3,4)로 나눠서 7을 2칸 전진시키거나, (2,4), (3,5)로 6과 8을, 또는 (2,3), (4,5)로 5와 9를 전진시킬 수 있습니다.
* 눈금 4, 4, 4, 6이 나온 경우, 어떻게 조합하든 (4,4), (4,6), 즉 8과 10을 전진시킬 수밖에 없습니다.
===말의 전진===
한 턴에는 최대 3개의 열까지만 전진시킬 수 있습니다. 이 열은 모두가 공유하는 3개의 검정색 말로 표시합니다. 다만, 전진을 거부할 수는 없습니다. 이미 자신의 말이 있었다면, 그 다음 칸부터 검정색 말의 전진이 시작됩니다.
예시 :
* 검정색 말을 하나도 올리지 않은 채로 (2,3), (4,5)를 이동시키고자 합니다. 이 경우, 5번 열과 9번 열에 검정색 말을 올리게 되며, 어느 하나에만 올릴 수는 없습니다.
* 검정색 말을 4번 열과 5번 열에 올린 채로 (2,3), (4,5)를 이동시키고자 합니다. 이 경우, 9번 열에 추가로 검정색 말을 올리게 되며, 5번 말에 있던 검정색 말은 한 칸 더 전진합니다.
* 검정색 말을 2번 열과 3번 열에 올린 채로 (2,3), (4,5)를 이동시키고자 합니다. 이 경우, 5번 열과 9번 열 중 하나만 골라 검정색 말을 올리게 됩니다.
* 검정색 말을 2번, 3번, 12번 열에 올린채로 눈금 2, 3, 4, 5를 얻었습니다. 이 경우, 어떤 조합을 하든 눈금을 움직일 수 없으며, 강제로 턴을 잃게 됩니다. ('''턴 종료'''를 참조하세요.)
===턴 종료===
턴 종료는 크게 2가지 경우로 나뉩니다. 첫번째는 플레이어가 자의로 턴을 종료하는 경우이고, 두번째는 위의 예시처럼 어떻게 해도 말을 움직일 수 없는 경우입니다.
* 턴을 자의로 종료한 경우, 현재 검정색 말의 위치에 자신의 색깔 말을 올립니다. 이미 그 열에 자신의 말이 있다면 해당 위치로 올립니다.
* 턴을 강제로 종료당한 경우, 현재 검정색 말을 그대로 치웁니다. 즉, 이번 턴의 행동을 모두 잃게 됩니다.
Examples:
* 7번 열에서 3칸, 8번 열에서 2칸, 9번 열에서 1칸을 전진하고 턴을 자의로 종료했습니다. 만일 이 플레이어가 이전에 7번 열에서 4칸을 전진했었다면, 턴 종료 후 7번 열에서 7칸 앞에 있게 되는 것입니다. 나머지 열도 그대로 전진합니다.
* 7번 열에서 3칸, 8번 열에서 2칸, 9번 열에서 1칸을 전진하고 턴을 강제로 종료했습니다. 만일 이 플레이어가 이전에 7번 열에서 4칸을 전진했었다면, 턴 종료 후 7번 열에서 4칸을 유지하게 됩니다. 나머지 열의 진행 상황도 유지됩니다.
===열의 완성 (점수 득점)===
한 플레이어가 어느 열의 골인 시점에 도달한 후 자의로 턴을 종료한다면, 그 플레이어가 해당 열을 점령합니다. 해당 열은 그 플레이어의 차지가 되며, 더 이상 그 열에서 전진할 수 없습니다. 그 뒤, 해당 플레이어는 1점을 획득합니다.
===승리 조건===
가장 먼저 3점을 획득하면 승리합니다.
==기본 전략==
기본적으로 이 게임은 언제 멈춰야 하는지에 모든 것이 달려있습니다. 주사위 운으로 3점을 한 턴만에 따내고 우승하는 경우는 없다시피 하며, 그렇기 때문에 강제로 모든 것을 날리기 전에 턴을 멈추는 것이 중요합니다. 다만, 너무 적게 전진할 경우 다른 플레이어가 자신을 역전할 수도 있으므로, 언제 멈출지를 고민하는 것이 중요합니다.
7의 경우 총 6가지 경우의 수가 있지만, 2나 12같은 경우 1가지 경우의 수밖에 없습니다. 그렇기 때문에 2번 열과 12번의 열의 길이는 7번 열의 길이에 비해 짧습니다. 이를 참고하여 중앙을 점령할지, 아니면 양 옆을 점령할지에 따라 전략이 나뉠 수도 있습니다.
70e0f1692d1b9de3b186fe53d299da6743c06971
Gamehelpakeruption
0
176
1228
2016-12-13T10:21:28Z
Yooyou7
6164
새 문서: =화산 폭발!= 화산 폭발은 간단히 요약하면 자신의 마을을 살리기 위해 다른 마을을 불태우는 게임입니다. 게임의 기본적인 목적은 다른 ...
wikitext
text/x-wiki
=화산 폭발!=
화산 폭발은 간단히 요약하면 자신의 마을을 살리기 위해 다른 마을을 불태우는 게임입니다. 게임의 기본적인 목적은 다른 마을에 용암을 연결시키고, 이를 통해 자신의 마을을 지키는 것으로 진행됩니다.
==게임 규칙==
===턴의 진행===
턴은 일반적으로 아래의 4단계를 거쳐 진행됩니다.
====온도 체크====
먼저, 자신의 마을의 온도가 얼마나 올라가게 될지를 확인합니다. (10도 당 1칸)
* 벽으로 방어되지 않은 용암 줄기 당 20도가 상승합니다.
* 벽으로 방어된 용암 줄기는 주사위를 굴려서 벽이 파괴될지를 확인합니다. 벽이 파괴되면 10도, 파괴되지 않으면 0도 상승합니다.
만일 이로 인해 위험 지역 레벨이 상승하게 된다면, 상승한 레벨에 따라 해당 보너스를 받습니다.
* 레벨 1로 상승하게 되면, (1) 이번 턴에 벽을 2개까지 놓을 수 있습니다.
* 레벨 2로 상승하게 되면, (1) 이번 턴에 벽을 2개까지 놓을 수 있으며, (2) 카드 1장을 추가로 받습니다.
* 레벨 3으로 상승하게 되면, (1) 이번 턴에 벽을 2개까지 놓을 수 있으며, (2) 카드 1장을 추가로 받고, (3) 원한다면 용암 타일을 하나 더 놓습니다.
또한, 그 플레이어가 최초로 어떤 레벨을 달성한다면, 추가로 폭발 타일을 받습니다. ('''폭발 타일'''을 참조하세요.)
====타일 배치====
온도 확인이 끝나면, 플레이어는 중앙에서 타일 하나를 받아 배치해야 합니다.
타일 배치에는 아래와 같은 조건이 따릅니다.
* 각 타일은 반드시 보드의 육각형 칸 안에 배치되어야 합니다.
* 인접된 모든 타일과 용암이 연결되어야 합니다.
* 타일이 있는 경우, 용암이 없는 변으로 용암이 흐를 수는 없습니다. (단, 벽 밖이나 마을로 나갈 수는 있음)
* 최소 하나의 타일과 용암이 연결되어야 합니다.
위와 같이 배치한 후, 자신이 연결한 타일의 용암이 '''주인이 없는 마을을 포함'''하여 마을과 닿을 경우, 닿게 한 용암 1줄기 당 '''액션 카드''' 1장을 받습니다.
====액션 카드====
타일 배치가 끝난 뒤, 액션 카드를 사용할 수 있습니다.
액션 카드의 목록은 다음과 같습니다.
* 여진 (Aftershock) 5장 [돌] - 맵 위의 타일 중 하나를 회전시킵니다. 단, 타일 배치의 규칙을 만족시켜야 합니다.
* 지진 (Quake) 5장 [돌] - 맵 위의 타일 중 하나를 자신이 새롭게 받은 타일과 교체합니다. 이전에 있던 타일과 그 위에 있던 벽은 제거됩니다. 단, 타일 배치의 규칙을 만족시켜야 합니다.
* 함락공 (Sinkhole) 4장 [나무] - 맵 위의 타일 중 하나와 그 위에 있던 벽을 제거합니다. 단, 타일 배치의 규칙을 만족시켜야 합니다.
* 화산 폭탄 (Volcanic Bomb) 4장 [나무] - 맵 위의 벽 중 하나를 제거합니다.
* 비 (Rain) 6장 [나무] - 자신의 마을의 온도를 즉시 30도 낮춥니다.
* 재배치 (Relocate) 5장 [밀짚] - 자신의 마을 위의 벽들을 어떤 위치로든 재배치할 수 있습니다. 단, 한 곳에 2개 이상에 벽이 있을 순 없습니다.
* 강화 (Reinforce) 6장 [밀짚] - 이번 턴이 끝날 때, 벽을 하나 더 설치할 수 있습니다.
* 용암류 (Lava Flow) 3장 [밀짚] - 새로운 용암 타일을 받아 타일 배치의 규칙에 맞게 배치합니다.
지진, 여진, 용암류의 경우, 닿지 않았던 곳에 용암이 닿는다면 역시 용암 1줄기 당 액션 카드 1장을 추가로 받습니다.
액션 카드는 총 3가지 용도로 사용할 수 있습니다.
* 액션 카드의 효과를 발동할 수 있습니다.
* 액션 카드를 버리고 해당 카드에 적힌 벽을 받을 수 있습니다.
* 액션 카드 2장을 버리고 용암 타일을 추가로 받을 수 있습니다.
턴 종료 후 액션 카드는 3장까지 보유할 수 있습니다.
액션 카드가 모두 소진되면 사용된 카드 덱을 다시 섞습니다.
====벽 배치====
모든 것이 종료되면, 벽 하나를 배치할 수 있습니다.
벽은 밀짚, 나무, 돌 3가지가 있으며, 해당 벽들은 필드 위의 해당 칸에 타일을 올려 획득하거나 카드를 버려 획득할 수 있습니다.
벽은 크게 2가지 용도로 사용될 수 있습니다.
* 필드 위의 용암 타일을 막는 용도로 사용할 경우. 이 경우, 어떤 사람이 벽에 막힌 용암과 연결을 짓고자 한다면 주사위를 굴립니다. 벽이 파괴된다면 그대로 배치하나, 파괴되지 않는다면 다른 곳에 배치해야 합니다.
* 자신의 마을을 방어하는 용도로 사용할 경우. 이 경우, 그 벽에 용암 타일이 연결된다면 매 턴 시작시 주사위를 굴립니다. 벽이 파괴된다면 마을의 온도가 10도 상승합니다.
벽의 파괴는 주사위를 굴려 결정합니다. 용암 측과 벽 측은 주사위를 하나씩 굴리며, 더 높은 측이 승리합니다. 동점의 경우 용암이 승리하며, 용암이 승리하면 벽은 파괴됩니다. 밀짚 벽은 +0, 나무 벽은 +1, 돌 벽은 +2만큼을 벽 측의 주사위에 추가합니다.
===폭발 타일===
각 위험 지역 레벨을 최초로 올리게 된다면, 폭발 타일을 받습니다.
폭발 타일은 6방향으로 전부 용암이 나있는 용암의 근원지이며, 다른 타일과 연결되지 않아도 됩니다.
다만, 그 외의 타일 배치의 규칙은 만족하여야 합니다.
폭발 타일이 배치되면, 해당자를 제외한 모든 사람은 기온을 30도 올립니다.
위험 지역을 2개 이상 개척하여 폭발 타일을 2개 이상 받더라도, 한 턴에 1개씩만 배치합니다.
===게임의 종료===
게임은 누군가가 온도계의 끝까지 이동하거나, 중앙의 용암 타일이 모두 소진되면 게임 종료가 발동됩니다.
모든 플레이어는 마지막 턴을 수행하며, 이 경우 용암 타일은 배치하지 않습니다.
온도가 가장 낮은 사람이 게임에서 승리합니다!
===변형 가능 규칙===
====비 카드 제외====
액션 카드 중, 비 카드 5장을 게임에서 제외합니다.
4fa1972627e33b90cdc87e51ef705beb2c552978
1229
1228
2016-12-13T10:22:04Z
Yooyou7
6164
wikitext
text/x-wiki
=화산 폭발!=
화산 폭발은 간단히 요약하면 자신의 마을을 살리기 위해 다른 마을을 불태우는 게임입니다. 게임의 기본적인 목적은 다른 마을에 용암을 연결시키고, 이를 통해 자신의 마을을 지키는 것으로 진행됩니다.
==게임 규칙==
===턴의 진행===
턴은 일반적으로 아래의 4단계를 거쳐 진행됩니다.
====온도 체크====
먼저, 자신의 마을의 온도가 얼마나 올라가게 될지를 확인합니다. (10도 당 1칸)
* 벽으로 방어되지 않은 용암 줄기 당 20도가 상승합니다.
* 벽으로 방어된 용암 줄기는 주사위를 굴려서 벽이 파괴될지를 확인합니다. 벽이 파괴되면 10도, 파괴되지 않으면 0도 상승합니다.
만일 이로 인해 위험 지역 레벨이 상승하게 된다면, 상승한 레벨에 따라 해당 보너스를 받습니다.
* 레벨 1로 상승하게 되면, (1) 이번 턴에 벽을 2개까지 놓을 수 있습니다.
* 레벨 2로 상승하게 되면, (1) 이번 턴에 벽을 2개까지 놓을 수 있으며, (2) 카드 1장을 추가로 받습니다.
* 레벨 3으로 상승하게 되면, (1) 이번 턴에 벽을 2개까지 놓을 수 있으며, (2) 카드 1장을 추가로 받고, (3) 원한다면 용암 타일을 하나 더 놓습니다.
또한, 그 플레이어가 최초로 어떤 레벨을 달성한다면, 추가로 폭발 타일을 받습니다. ('''폭발 타일'''을 참조하세요.)
====타일 배치====
온도 확인이 끝나면, 플레이어는 중앙에서 타일 하나를 받아 배치해야 합니다.
타일 배치에는 아래와 같은 조건이 따릅니다.
* 각 타일은 반드시 보드의 육각형 칸 안에 배치되어야 합니다.
* 인접된 모든 타일과 용암이 연결되어야 합니다.
* 타일이 있는 경우, 용암이 없는 변으로 용암이 흐를 수는 없습니다. (단, 벽 밖이나 마을로 나갈 수는 있음)
* 최소 하나의 타일과 용암이 연결되어야 합니다.
위와 같이 배치한 후, 자신이 연결한 타일의 용암이 '''주인이 없는 마을을 포함'''하여 마을과 닿을 경우, 닿게 한 용암 1줄기 당 '''액션 카드''' 1장을 받습니다.
====액션 카드====
타일 배치가 끝난 뒤, 액션 카드를 사용할 수 있습니다.
액션 카드의 목록은 다음과 같습니다.
* 여진 (Aftershock) 5장 [돌] - 맵 위의 타일 중 하나를 회전시킵니다. 단, 타일 배치의 규칙을 만족시켜야 합니다.
* 지진 (Quake) 5장 [돌] - 맵 위의 타일 중 하나를 자신이 새롭게 받은 타일과 교체합니다. 이전에 있던 타일과 그 위에 있던 벽은 제거됩니다. 단, 타일 배치의 규칙을 만족시켜야 합니다.
* 함락공 (Sinkhole) 4장 [나무] - 맵 위의 타일 중 하나와 그 위에 있던 벽을 제거합니다. 단, 타일 배치의 규칙을 만족시켜야 합니다.
* 화산 폭탄 (Volcanic Bomb) 4장 [나무] - 맵 위의 벽 중 하나를 제거합니다.
* 비 (Rain) 6장 [나무] - 자신의 마을의 온도를 즉시 30도 낮춥니다.
* 재배치 (Relocate) 5장 [밀짚] - 자신의 마을 위의 벽들을 어떤 위치로든 재배치할 수 있습니다. 단, 한 곳에 2개 이상에 벽이 있을 순 없습니다.
* 강화 (Reinforce) 6장 [밀짚] - 이번 턴이 끝날 때, 벽을 하나 더 설치할 수 있습니다.
* 용암류 (Lava Flow) 3장 [밀짚] - 새로운 용암 타일을 받아 타일 배치의 규칙에 맞게 배치합니다.
지진, 여진, 용암류의 경우, 닿지 않았던 곳에 용암이 닿는다면 역시 용암 1줄기 당 액션 카드 1장을 추가로 받습니다.
액션 카드는 총 3가지 용도로 사용할 수 있습니다.
* 액션 카드의 효과를 발동할 수 있습니다.
* 액션 카드를 버리고 해당 카드에 적힌 벽을 받을 수 있습니다.
* 액션 카드 2장을 버리고 용암 타일을 추가로 받을 수 있습니다.
턴 종료 후 액션 카드는 3장까지 보유할 수 있습니다.
액션 카드가 모두 소진되면 사용된 카드 덱을 다시 섞습니다.
====벽 배치====
모든 것이 종료되면, 벽 하나를 배치할 수 있습니다.
벽은 밀짚, 나무, 돌 3가지가 있으며, 해당 벽들은 필드 위의 해당 칸에 타일을 올려 획득하거나 카드를 버려 획득할 수 있습니다.
벽은 크게 2가지 용도로 사용될 수 있습니다.
* 필드 위의 용암 타일을 막는 용도로 사용할 경우. 이 경우, 어떤 사람이 벽에 막힌 용암과 연결을 짓고자 한다면 주사위를 굴립니다. 벽이 파괴된다면 그대로 배치하나, 파괴되지 않는다면 다른 곳에 배치해야 합니다.
* 자신의 마을을 방어하는 용도로 사용할 경우. 이 경우, 그 벽에 용암 타일이 연결된다면 매 턴 시작시 주사위를 굴립니다. 벽이 파괴된다면 마을의 온도가 10도 상승합니다.
벽의 파괴는 주사위를 굴려 결정합니다. 용암 측과 벽 측은 주사위를 하나씩 굴리며, 더 높은 측이 승리합니다. 동점의 경우 용암이 승리하며, 용암이 승리하면 벽은 파괴됩니다. 밀짚 벽은 +0, 나무 벽은 +1, 돌 벽은 +2만큼을 벽 측의 주사위에 추가합니다.
===폭발 타일===
각 위험 지역 레벨을 최초로 올리게 된다면, 폭발 타일을 받습니다.
폭발 타일은 6방향으로 전부 용암이 나있는 용암의 근원지이며, 다른 타일과 연결되지 않아도 됩니다.
다만, 그 외의 타일 배치의 규칙은 만족하여야 합니다.
폭발 타일이 배치되면, 해당자를 제외한 모든 사람은 기온을 30도 올립니다.
위험 지역을 2개 이상 개척하여 폭발 타일을 2개 이상 받더라도, 한 턴에 1개씩만 배치합니다.
===게임의 종료===
게임은 누군가가 온도계의 끝까지 이동하거나, 중앙의 용암 타일이 모두 소진되면 게임 종료가 발동됩니다.
모든 플레이어는 마지막 턴을 수행하며, 이 경우 용암 타일은 배치하지 않습니다.
온도가 가장 낮은 사람이 게임에서 승리합니다!
==변형 가능 규칙==
===비 카드 제외===
액션 카드 중, 비 카드 5장을 게임에서 제외합니다. 이를 통해 비 카드가 가져오는 운적 요소를 줄일 수 있을 것입니다.
b0761202598c02191310d75204e653d0a24c4677
Gamehelploveletter
0
177
1231
2017-02-12T14:14:06Z
Baesinja
6364
새 문서: 승리 조건<br> - 모든 인원이 탈락하고 1명만 남았을 경우 승리<br> - 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사...
wikitext
text/x-wiki
승리 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우 승리<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
- 토큰을 다 모았을 경우 승리<br>
(2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명이 플레이 할 경우, 4개)<br>
<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다<br>
2. 2장의 카드를 비교 후, 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다<br>
<br>
카드 기능<br>
1. 경비병: 상대방이 가진 카드를 추측(병사를 제외한 추측)하고 추측이 맞았을 경우에는 상대방은 탈락한다<br>
2. 성직자: 다른 1명의 카드를 볼 수 있다<br>
3. 남작: 다른 1명을 지목하여 대결한다. 손에 든 카드의 숫자가 더 낮은 사람은 라운드에서 탈락한다<br>
4. 시녀: 다음 차례가 올 때까지 어떠한 카드의 효과도 받지 않는다<br>
5. 왕자: 자신이나 다른 1명을 지목해 손에 든 모든 카드를 버리게 하고 다시 덱에서 한 장 가져온다<br>
6. 왕: 다른 1명과 자신의 카드를 모두 바꾼다<br>
7. 백작부인: 5번 또는 6번(왕자, 왕) 카드와 같이 들고 있다면 반드시 이 카드를 버린다<br>
8. 공주: 이 카드를 버리게 되면 라운드에서 탈락한다<br>
[http://cafe.naver.com/edugameschool/9785 보약게임]
3d93047e4bea8135385dc28b8d149ae9190da390
Tips stoneage
0
178
1232
2017-06-18T00:13:03Z
Masskizar
6411
새 문서: 금 모아서 같은 자원 사용하는 건물 많이 지으면 됨
wikitext
text/x-wiki
금 모아서 같은 자원 사용하는 건물 많이 지으면 됨
c3a324692f8b9f269186387e88525f13931d78a9
Gamehelpincangold
0
179
1233
2017-07-12T06:40:12Z
Ggong64
6425
새 문서: 탐험 덱은 다음과 같은 카드로 구성됩니다. 14 개 보물 카드 (1, 2, 3, 4, 5, 5, 7, 7, 9, 11, 11, 13, 14, 15 개 보석) 15 개의 위험 카드 (화재, 미라, 바...
wikitext
text/x-wiki
탐험 덱은 다음과 같은 카드로 구성됩니다.
14 개 보물 카드 (1, 2, 3, 4, 5, 5, 7, 7, 9, 11, 11, 13, 14, 15 개 보석)
15 개의 위험 카드 (화재, 미라, 바위, 뱀, 거미 각각 3 개)
5 개의 아티팩트 카드
게임이 시작될 때, 모든 보물과 위험 카드는 덱에 섞여 있지만 아티팩트는 아무 것도 없습니다.
게임은 5 개의 탐험으로 나뉩니다. 다섯 번의 원정 후 가장 많은 점수를 얻은 플레이어가 승리합니다. 모든 원정대는 같은 방식으로 진행됩니다.
원정대가 시작될 때, 하나의 이슈 카드가 덱에 추가 된 다음 덱이 섞입니다. 모든 플레이어가 탐험에 들어갈 것입니다. 그런 다음 원정대는 여러 라운드에서 진행됩니다.
각 라운드, 덱에서 카드가 공개됩니다. 다음 중 하나가 발생할 수 있습니다.
1.보물 카드가 공개된다. 보물 카드는 많은 보석을 보여줍니다. 여전히 원정대에있는 플레이어들에게 똑같이 나누십시오. 남은 음식은 카드에 남아 있습니다.
2.위험의 카드가 공개된다. 그것이 원정 중 최초의 위험 카드라면 아무 일도 일어나지 않습니다. 두 번째라면 원정대가 실패합니다. 아래를보십시오.
3.유물의 카드가 공개된다. 아무 반응이 없습니다.
원정대는 아직 (같은 종류로 인해 두 가지 위험을) 실패하지 않을 경우 그 후, 각 플레이어는 캠프를 유지 탐험 또는 은퇴의 여부를 결정하게됩니다. 그들은 비밀리에 결정을 내리고 결정은 동시에 드러납니다.
은퇴 하기로 선택한 사람들은 더 이상 탐험에 참여하지 않습니다. 첫째, 남은 보석 (보물 카드가 공개되었을 때 나머지는 똑같이 나누어 줄 수없는 나머지 카드)을 가져옵니다. 이들은 은퇴하는 사람들에게 동등하게 분배합니다. 남은 보석은 여전히 카드에 남아 있습니다. 원정대에서 주장한 모든 보석은 현재 안전하고 분실되지 않습니다. 또한, 은퇴 한 사람이 정확히 한 명이라면 원정대에서 공개 된 모든 Artifact 카드를 가져 가야 합니다 .
플레이어가 은퇴하면 보석을 장막 안으로 가져옵니다. 각 플레이어의 텐트 내용은 숨겨져 있으므로 각 플레이어의 상금을 기억하는 것이 가장 좋습니다.
그 후, 원정대에 아직도 사람들이 있다면, 다음 라운드를 계속하십시오. 그렇지 않으면 원정대가 끝납니다.
원정대는 같은 종류의 2 장의 해저드 카드가 공개되면 조기에 끝날 수 있습니다. 이 경우에도 원정대에 남아있는 모든 사람은 원정대 에서 보석을 얻지 못합니다 . 두 개의 동일한 위험 카드 중 하나가 갑판에서 영구적으로 제거 되므로 나머지 게임에는 해당 종류의 위험 카드가 하나 더 적습니다.
원정대가 모든 사람이 은퇴하는지 아니면 같은 종류의 위험 카드 2 장이 공개되는지에 관계없이 주장되지 않은 모든 유물 은 덱에서 영구적으로 제거됩니다 .
다섯 번의 탐험 그 최종 점수가 매겨집니다. 성공적으로 돌아온 각 보석 (원정 중 길을 잃지 않았 음)은 1 점입니다. 유물은 5점이며, 마지막 두 개의 유물을 수집 할 때 5 개의 추가 보석을 얻습니다. 가장 많은 점수를 얻은 플레이어가 승리합니다 (동점일 경우 가장 많은 이슈(카드)를 얻은 플레이어가 승리합니다).
4f18ebb7a7031269102ece14027ac78ef0c93554
1234
1233
2017-08-09T13:55:22Z
Yoonh
6434
wikitext
text/x-wiki
탐험 덱은 다음과 같은 카드로 구성됩니다.
-14 개 보물 카드 (1, 2, 3, 4, 5, 5, 7, 7, 9, 11, 11, 13, 14, 15 개 보석)
-15 개의 위험 카드 (화재, 미라, 바위, 뱀, 거미 각각 3 개)
-5 개의 아티팩트 카드
게임이 시작될 때, 모든 보물과 위험 카드는 덱에 섞여 있지만 아티팩트는 아무 것도 없습니다.
게임은 5 개의 탐험으로 나뉩니다.
다섯 번의 원정 후 가장 많은 점수를 얻은 플레이어가 승리합니다. 모든 원정대는 같은 방식으로 진행됩니다.
원정대가 시작될 때, 하나의 이슈 카드가 덱에 추가 된 다음 덱이 섞입니다. 모든 플레이어가 탐험에 들어갈 것입니다. 그런 다음 원정대는 여러 라운드에서 진행됩니다.
각 라운드, 덱에서 카드가 공개됩니다. 다음 중 하나가 발생할 수 있습니다.
1.보물 카드가 공개된다. 보물 카드는 많은 보석을 보여줍니다. 여전히 원정대에있는 플레이어들에게 똑같이 나누십시오. 남은 음식은 카드에 남아 있습니다.
2.위험의 카드가 공개된다. 그것이 원정 중 최초의 위험 카드라면 아무 일도 일어나지 않습니다. 두 번째라면 원정대가 실패합니다. 아래를보십시오.
3.유물의 카드가 공개된다. 아무 반응이 없습니다.
원정대는 아직 (같은 종류로 인해 두 가지 위험을) 실패하지 않을 경우 그 후, 각 플레이어는 캠프를 유지 탐험 또는 은퇴의 여부를 결정하게됩니다.
그들은 비밀리에 결정을 내리고 결정은 동시에 드러납니다.
은퇴 하기로 선택한 사람들은 더 이상 탐험에 참여하지 않습니다. 첫째, 남은 보석 (보물 카드가 공개되었을 때 나머지는 똑같이 나누어 줄 수없는 나머지 카드)을 가져옵니다. 이들은 은퇴하는 사람들에게 동등하게 분배합니다. 남은 보석은 여전히 카드에 남아 있습니다.
원정대에서 주장한 모든 보석은 현재 안전하고 분실되지 않습니다. 또한, 은퇴 한 사람이 정확히 한 명이라면 원정대에서 공개 된 모든 Artifact 카드를 가져 가야 합니다 .
플레이어가 은퇴하면 보석을 장막 안으로 가져옵니다. 각 플레이어의 텐트 내용은 숨겨져 있으므로 각 플레이어의 상금을 기억하는 것이 가장 좋습니다.
그 후, 원정대에 아직도 사람들이 있다면, 다음 라운드를 계속하십시오. 그렇지 않으면 원정대가 끝납니다.
원정대는 같은 종류의 2 장의 해저드 카드가 공개되면 조기에 끝날 수 있습니다. 이 경우에도 원정대에 남아있는 모든 사람은 원정대 에서 보석을 얻지 못합니다 . 두 개의 동일한 위험 카드 중 하나가 갑판에서 영구적으로 제거 되므로 나머지 게임에는 해당 종류의 위험 카드가 하나 더 적습니다.
원정대가 모든 사람이 은퇴하는지 아니면 같은 종류의 위험 카드 2 장이 공개되는지에 관계없이 주장되지 않은 모든 유물 은 덱에서 영구적으로 제거됩니다 .
다섯 번의 탐험 그 최종 점수가 매겨집니다. 성공적으로 돌아온 각 보석 (원정 중 길을 잃지 않았 음)은 1 점입니다. 유물은 5점이며, 마지막 두 개의 유물을 수집 할 때 5 개의 추가 보석을 얻습니다.
가장 많은 점수를 얻은 플레이어가 승리합니다 (동점일 경우 가장 많은 이슈(카드)를 얻은 플레이어가 승리합니다).
ff470afa559b03ef2b41ebda0757fc8ce45c08b2
1235
1234
2017-08-15T16:14:45Z
Kimochihak
6439
게임 해보고 이해하기 어려웠던 기존 글을 조금 다듬었습니다
wikitext
text/x-wiki
탐험 덱은 다음과 같은 카드로 구성됩니다.
-14 개 보물 카드 (1, 2, 3, 4, 5, 5, 7, 7, 9, 11, 11, 13, 14, 15 개의 보석)
-15 개의 위험 카드 (화재, 미라, 바위, 뱀, 거미 각각 3 개)
-5 개의 유물 카드
게임이 시작될 때, 모든 보물카드와 위험 카드는 덱에 섞여 있지만 유물카드는 섞여 있지 않습니다.
게임은 다섯번의 원정으로 나뉘며 각 원정당 여러 라운드(탐험)가 존재합니다
다섯 번의 원정 후 가장 많은 점수를 얻은 플레이어가 승리합니다. 모든 원정은 같은 방식으로 진행됩니다.
원정이 시작될 때, 하나의 유물 카드가 덱에 추가 된 다음 덱이 섞입니다. 모든 플레이어가 자동으로 탐험에 들어갑니다. 그런 다음 원정대는 여러번의 탐험을 진행합니다.
각 탐험마다 덱에서 카드가 공개됩니다. 공개되는 카드는 다음 중 하나입니다.
1.보물 카드. 보물 카드는 카드에 쓰여있는 숫자만큼의 보석을 줍니다. 원정대에있는 플레이어들은 똑같이 보석을 나누게 되고 남은 보석은 카드에 남습니다.
(ex 보석11개짜리 카드가 나왔고 탐험가가 6명일경우 각1개씩 나눠갖고 그 카드 위에 5개의 보석이 남습니다.)
2.위험 카드. 그 카드가 원정 중 최초의 위험 카드라면 아무 일도 일어나지 않습니다. 공개된 위험카드와 같은 종류의 위험카드라면 원정대가 실패합니다. 밑에 자세한 설명을 보세요.
3.유물 카드. 아무 일도 일어나지 않습니다.
원정이 아직 (같은 종류의 위험카드로 인한 ) 실패를 하지 않은 경우, 각 플레이어는 탐험 또는 귀환 중 하나를 결정하게 됩니다.
비밀리에 결정을 내리고 결정은 동시에 드러납니다.
귀환 하기로 선택한 사람들은 더 이상 탐험에 참여하지 않습니다. 남은 보석 (보물 카드가 공개되었을 때 똑같이 나누고 남은것)을 가져옵니다.
이 보석은 귀환하는 사람들에게 동등하게 분배합니다. 분배 후 남는 보석은 여전히 카드에 남습니다.
귀환을 하게되면 원정대에서 얻은 모든 보석은 완전히 당신의 것이 됩니다. 또한, 귀환을 한 사람이 한 명이라면 원정대에서 공개 된 모든 유물 카드를 가져갑니다 .
플레이어가 귀환을 하면 보석을 텐트 안으로 가져옵니다. 각 플레이어의 텐트 내용은 비공개이므로 각 플레이어가 획득한 보석을 기억하는 것이 좋습니다.
그 다음 원정대에 아직도 사람들이 있다면 다음 탐험을 계속하게 됩니다. 모두 귀환을 했다면 원정이 끝나고 다음 원정을 준비합니다.
같은 종류 두장의 위험 카드가 공개되면 그 원정은 실패하게 됩니다. 이 경우 귀환하지 않고 원정대에 남아있는 모든 사람은 그 원정에서 획득했던 보석들을 텐트로 가져갈 수 없습니다.
그리고 두 개의 동일한 위험 카드 중 하나가 덱에서 영구적으로 제거 되므로 나머지 게임에는 해당 종류의 위험 카드가 하나 더 적습니다.(위의 설명에 있듯이 5종류의 위험 카드는 3장씩있습니다)
원정 중 공개된 유물은
두명이상의 인원이 귀환을 하여 가져가지 못했거나
같은 종류의 위험 카드 두장이 공개되어 원정이 실패한것에 관계없이
그 원정에서 획득되지 못한 유물은 덱에서 영구적으로 제거됩니다 .
다섯 번의 원정 후 최종 점수가 매겨집니다. 성공적으로 획득한 보석은 개당 1 점입니다. 유물은 5점이며, 다섯개 중 마지막 두 개의 유물은 수집 할 때 5 개의 추가 보석을 얻습니다.(1,2,3유물은 5점 4,5번유물은10점)
가장 많은 점수를 얻은 플레이어가 승리합니다 (동점일 경우 가장 많은 유물 카드를 얻은 플레이어가 승리합니다).
기존 설명이 번역기 같아서 이해하기 쉽도록 다듬었습니다.
한국인들이 아는 게임 5~6개 말고 다른 게임들도 할수 있도록 번역에 같이 힘썼으면 좋겠어요
광복절에 대한민국 만세입니다
4b70c776ad35ac2b7ec57893057dbd67e80fee3d
Gamehelpdungeonroll
0
180
1236
2020-11-01T10:58:58Z
Soler125
7104
z
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Tips coltexpress
0
181
1237
2020-12-20T09:09:49Z
MuLPasS
7180
새 문서: 나도 몰라 니들이 알아서 해
wikitext
text/x-wiki
나도 몰라 니들이 알아서 해
bf22c580284f28fe3e62cdc2c80c844fcd8988a6
Gamehelpcubirds
0
182
1238
2021-01-04T16:44:18Z
Soyounghan09
7197
새 문서: [모아보새 - Cubirds] 이 게임의 목적은 7가지의 다른 종류의 카드를 1장 이상씩 모으거나, 2가지 종류의 카드를 3장 이상 모으는 것 입니다....
wikitext
text/x-wiki
[모아보새 - Cubirds]
이 게임의 목적은 7가지의 다른 종류의 카드를 1장 이상씩 모으거나, 2가지 종류의 카드를 3장 이상 모으는 것 입니다.
A game plays in several rounds. At the beginning of each round, each player starts with 8 cards in their hand and there are 4 rows with three cards faceup at the center of the table. The game starts with the dealer and go clockwise. Also, each player starts with a bird card, faceup, in front of them, which represents the first Bird in their collection.
게임은 여러 라운드로 진행됩니다. 각각의 라운드의 처음에, 각각의 플레이어는 8장의 카드를 가지고 시작합니다. 테이블의 중앙에는 3장의 카드씩 4 줄이 놓여 있습니다. 게임은 선부터 시계방향으로 진행됩니다. 또한, 각각의 플레이어는 한 장의 새카드를 앞면으로 두는데, 그것은 첫번째 새의 종류의 묶음을 나타냅니다.
Turn of a player - On their turn, a player must lay one or more birds from their hand. All the birds of the chosen specie that player have in their hand must be played. The player lays these birds (next to each other) on the left or the right side of one of the 4 rows at the center of the table. When a player places a bird in a row that already has one or more Birds of that species, the player must take all the cards between these birds into their hand. After taking the surrounded cards, remaining birds are put together and new cards are added (placed on the left or the right) from the draw pile to this row until there are two different species in it.
플레이어의 턴 - 플레이어는 손에서 한개나 그 이상의 카드를 내려놓아야 합니다. 손안에 가지고 있는 선택된 종류의 모든 새들은 내려놓아져야 합니다. 플레이어는 이러한 새들을 (각자의 옆에) 테이블 가운데에 있는 4줄의 카드의 왼쪽이나 오른쪽에 놓습니다. 한 플레이어가 한개나 그 이상의 갯수가 이미 있는 종류의 줄에 새를 내려놓으면, 그 플레이어는 손안에 그 카드를 모두 가져가야 합니다. 주변의 카드를 가져간 후에, 남아있는 새들은 같이 놓여지고, 2가지의 다른 종류의 새카드가 놓여질 때까지 덱에서 새로운 카드가 추가됩니다. (왼쪽이나 오른쪽에 놓여져서)
If no cards were surrounded by birds of the same species, the player can’t take cards from the center of the table but they have the option to take two first cards from the draw pile to add them to their hand.
만약에 아무 카드도 같은 종의 새에 의해서 둘려쌓여지지 않는다면, 그 플레이어는 테이블의 가운데에서 카드를 가지올수 없지만, 덱에서 손에 추가할 두가지 첫번째 카드들을 가져갈 선택사항을 가집니다.
Complete a flock (optional) – a series of birds of the same species (a flock) that the player hold in their hand may be revealed to add one or two of this cards to their collection.
하나의 새 무리를 완성하기 (선택적) - 플레이어가 손에 가지고 있는 같은 종류의 새들의 묶음(새 무리)는 그들의 묶음에 한개 또는 두개 이상이 추가될 것입니다.
Each card has two numbers, the lower representing the number stated for the small flock and the higher representing the number stated for the big Flock. When the number of revealed cards is higher or equal to:
각각의 카드는 2개의 숫자를 가지고 있습니다. 낮은 숫자는 작은 새 무리에 대해 쓰여진 숫자를 나타내고, 더 높은 숫자는 큰 새 무리에 대해 쓰여진 숫자를 나타냅니다. 드러난 카드들의 숫자가 더 높거나 동등하다면 :
- the small flock, the player adds one of the revealed cards to their collection;
- 작은 새 무리의 플레이어는 드러난 카드들 중에 하나를 그들의 묶음에 더합니다.
- the big flock, the player adds two of the revealed cards to their collection.
-큰 무리의 새 플레이어는 드러난 카드들 중에서 2개를 그들의 묶음에 더합니다.
The remaining cards are placed into the discard pile. On their turn, a player can only complete a single Flock.
남은 카드들은 버려지는 더미에 놓여집니다. 한 플레이어는 턴에 하나의 새 무리만 완성할 수 있습니다.
End of a round - A round ends when one of the players has no cards left in their hand. The remaining cards that players have in their hand go to the discard pile. The cards laid in rows at the center of the table remain in place. The player who ended the round becomes the new dealer.
라운드의 끝 - 손에 카드가 남아 있지 않는 플레이어가 있다면 라운드가 끝납니다. 손에 남은 카드들은 버려지는 더미에 놓어집니다. 그 카드들은 중앙의 줄에 놓여집니다. 라운드를 끝낸 플레이어는 새로운 선이 됩니다.
End of the game – if a player completes the objective or if it is impossible to deal 8 cards to each player (even with the discard pile), the game ends immediately. In the second case, the player with the most bird cards in their collection wins the game.
게임의 종료 - 만약 한 플레이어가 목표를 달성하거나, 8개의 카드를 각각의 플레이어들에게 주는것이 불가능하다면 (버려진 카드 더미들을 포함하여), 게임이 즉시 끝납니다. 두번째 상황에서, 가장 많은 새 카드를 가진 사람이 승리합니다.
9b936d670573e12be84512455b3298396feca435
Gamehelpyatzy
0
122
1239
1115
2021-01-04T16:59:48Z
Soyounghan09
7197
wikitext
text/x-wiki
The game Yahtzee consists of 13 rounds. In each round, you roll 5 dice and then score the roll in a different category of your choice.
야찌는 13라운드로 이루어져 있습니다. 각각의 라운드에, 당신은 5개의 주사위들을 굴린 후에 당신의 선택에 따라서 다른 범위에 점수를 적습니다.
During a round, you can roll the dice up to three times before scoring -- the initial roll (in which you must roll all the dice), plus two optional re-rolls of any or all dice.
한 라운드 동안에, 당신은 그 주사위들을 점수를 적기 전에 3번 까지 굴릴 수 있습니다. - 첫번째 굴림 (당신이 모든 주사위를 굴려야 하는), 일부나 모든 주사위를 추가적으로 최대 2번까지 굴림.
There are 13 scoring categories, and each must be used for one of the 13 rounds. This often results in a zero score for some categories.
13개의 점수 범위들이 있고, 각각은 13라운드에 1개가 사용되어져야 합니다. 따라서 종종 몇몇의 범위에는 0점이 되기도 합니다.
The 13 scoring categories are as follows:
13개의 점수 범위들은 다음과 같습니다 :
1-6: There is one category for each number on the die. In these categories, the score is the sum of the pips on the dice of that number. For example, a roll of 1-1-2-5-5 could be scored as 2 points in the "ones" category, 2 points in the "twos" category, 10 points in the "fives" category, or 0 points in the "threes," "fours," or "sixes." If a player scores a total of at least 63 points across these six boxes, a bonus of 35 points is added.
1-6: 주사위의 각각의 수에 대해서 1개의 범위가 있습니다. 이 범위에서는, 점수는 주사위의 해당 숫자의 눈금의 합으로 메겨집니다. 예를들어서, 1-1-2-5-5의 굴림은 "1" 범위에서 2점으로 메겨질 수 있고, "2" 범주에서는 2점, "5"범위에서는 10점으로, "3, 4, 6"에는 0점으로 메겨질 수 있습니다. 만약 한 플레이어가 이러한 6개의 범위에서 총합이 63점 이상이라면, 보너스 35점이 추가됩니다.
7. Three-Of-A-Kind: At least three dice showing the same face -- Points equal the sum of all 5 dice (not just the 3 of a kind)
7. 같은 종류 3개 : 같은 면을 보여주는 최소한 3개의 주사위들 - 모든 5개의 주사위들의 총 합과 같은 점수 (한 종류의 3개의 점수만이 아니라)
8. Four-Of-A-Kind: At least four dice showing the same face -- Points equal the sum of all 5 dice (not just the 4 of a kind)
8. 같은 종류 4개 : 같은 면을 보여주는 최소한 4개의 주사위들 - 모든 5개의 주사위들의 총 합과 같은 점수 (한 종류의 4개의 점수만이 아니라)
9. Full House: A three-of-a-kind and a pair -- 25 points
9. 풀하우스 : 한 종류 3개와 한 종류 2개 - 25점
10. Small Straight: Four sequential dice 1-2-3-4, 2-3-4-5, or 3-4-5-6) -- 30 points
10. 스몰 스트레이트 : 4개의 순차적인 주사위들 (1-2-3-4, 2-3-4-5, 3-4-5-6) - 30점
11. Large Straight: Five sequential dice (1-2-3-4-5 or 2-3-4-5-6) -- 40 points
11. 라지 스트레이트 : 5개의 순차적인 주사위들 (1-2-3-4-5, 2-3-4-5-6) - 40점
12. Yahtzee: All five dice showing the same face -- 50 points (plus, once you have scored 50 pts for a Yahtzee, a 2nd Yahtzee gives a bonus of 100 points)
12. 야찌 : 같은 면을 보여주는 모든 5개의 주사위들 - 50점 (추가로, 첫번째 야찌에 50점을 획득하고, 2번째 야찌는 보너스 100점을 줍니다)
13. Chance: Any combination -- points equal the sum of all 5 dice
13. 찬스 : 아무 조합니다 - 5개의 주사위의 합과 같은 점수
b39e1b7849de8a0599e11f8fb80d0e9d3e794bbe
1243
1239
2021-01-22T14:03:59Z
Soyounghan09
7197
wikitext
text/x-wiki
야찌는 13라운드로 이루어져 있습니다. 각각의 라운드에, 당신은 5개의 주사위들을 굴린 후에 당신의 선택에 따라서 다른 범위에 점수를 적습니다.
한 라운드 동안에, 당신은 그 주사위들을 점수를 적기 전에 3번 까지 굴릴 수 있습니다. - 첫번째 굴림 (당신이 모든 주사위를 굴려야 하는), 일부나 모든 주사위를 추가적으로 최대 2번까지 굴림.
13개의 점수 범위들이 있고, 각각은 13라운드에 1개가 사용되어져야 합니다. 따라서 종종 몇몇의 범위에는 0점이 되기도 합니다.
13개의 점수 범위들은 다음과 같습니다 :
1-6: 주사위의 각각의 수에 대해서 1개의 범위가 있습니다. 이 범위에서는, 점수는 주사위의 해당 숫자의 눈금의 합으로 메겨집니다. 예를들어서, 1-1-2-5-5의 굴림은 "1" 범위에서 2점으로 메겨질 수 있고, "2" 범주에서는 2점, "5"범위에서는 10점으로, "3, 4, 6"에는 0점으로 메겨질 수 있습니다. 만약 한 플레이어가 이러한 6개의 범위에서 총합이 63점 이상이라면, 보너스 35점이 추가됩니다.
7. 같은 종류 3개 : 같은 면을 보여주는 최소한 3개의 주사위들 - 모든 5개의 주사위들의 총 합과 같은 점수 (한 종류의 3개의 점수만이 아니라)
8. 같은 종류 4개 : 같은 면을 보여주는 최소한 4개의 주사위들 - 모든 5개의 주사위들의 총 합과 같은 점수 (한 종류의 4개의 점수만이 아니라)
9. 풀하우스 : 한 종류 3개와 한 종류 2개 - 25점
10. 스몰 스트레이트 : 4개의 순차적인 주사위들 (1-2-3-4, 2-3-4-5, 3-4-5-6) - 30점
11. 라지 스트레이트 : 5개의 순차적인 주사위들 (1-2-3-4-5, 2-3-4-5-6) - 40점
12. 야찌 : 같은 면을 보여주는 모든 5개의 주사위들 - 50점 (추가로, 첫번째 야찌에 50점을 획득하고, 2번째 야찌는 보너스 100점을 줍니다)
13. 찬스 : 아무 조합이나 - 5개의 주사위의 합과 같은 점수
1fc68b7c022de93bc3ab77189bae3e76b6efd6a6
Gamehelpsaintpetersburg
0
183
1240
2021-01-18T09:09:52Z
Foresthan
7226
새 문서: https://blog.naver.com/lein/60022646132
wikitext
text/x-wiki
https://blog.naver.com/lein/60022646132
666cf8a171c025af46469889532fbcb1cae0cb37
Gamehelpnothanks
0
184
1241
2021-01-22T13:58:01Z
Soyounghan09
7197
카드의 숫자는 마이너스 / 칩의 숫자는 플러스
wikitext
text/x-wiki
OVERVIEW
The goal of No Thanks! is to be the player with the fewest points when all cards are taken. (In the BGA adaptation, points are negative.)
개요
노땡스의 목적은 모든 카드가 회수되었을 때 가장 적은 점수를 얻는 플레이어가 되는 것입니다. (보드게임 아레나에선 점수가 부정이라고 합니다.)
SETUP
Each player receives 11 chips. Nine cards are removed from the deck (of cards numbered 3-35) at random. The top card of the deck is revealed.
준비
각각의 선수는 11개의 칩을 받습니다. 3~35숫자 카드 중에서 9개의 카드는 랜덤으로 덱에서 제거됩니다. 덱의 맨 윗 카드는 보여집니다.
PLAY
On your turn, you may spend a chip or take the card along with all of the chips in the pile. If you spend a chip, your turn ends. If you take the card, the next card is revealed, and your turn continues.
The game ends when the last card is taken.
플레이하기
당신의 턴에, 당신은 칩을 소비하거나 더미에 있는 모든 칩과 카드를 가져갑니다. 만약에 칩을 소비하면 턴은 종료됩니다. 카드를 가져가면, 다음 카드가 보여지고 당신의 턴이 계속됩니다.
게임은 마지막 카드가 가져가지면 종료됩니다.
SCORING
Your score is the sum of your cards minus the number of chips you have. However, if you have cards with consecutive numbers, only the lowest number is added to your score.
Example: You have 5 chips and cards 3, 10, 11, 12, 13, and 20. Your score is 3 + 10 + 20 - 5 = 28.
The player with the lowest score is the winner.
점수 매기기
점수는 카드 숫자에서 당신이 가진 칩의 갯수를 뺀 것의 총합입니다. 하지만, 만약 연속되는 숫자의 카드를 가지고 있다면, 오직 가장 낮은 숫자만 점수에 더해집니다.
예시 : 5개의 칩과 카드 3, 10, 11, 12, 13, 과 20이 있다면, 점수는 3+10+20-5=28 입니다.
가장 낮은 점수를 가진 플레이어가 승자입니다.
712085ee6236e7dc41d44433153a9d6d6b6e6a3c
1242
1241
2021-01-22T14:00:47Z
Soyounghan09
7197
wikitext
text/x-wiki
개요
노땡스의 목적은 모든 카드가 회수되었을 때 가장 적은 점수를 얻는 플레이어가 되는 것입니다. (보드게임 아레나에선 점수가 부정이라고 합니다.)
준비
각각의 선수는 11개의 칩을 받습니다. 3~35숫자 카드 중에서 9개의 카드는 랜덤으로 덱에서 제거됩니다. 덱의 맨 윗 카드는 보여집니다.
플레이하기
당신의 턴에, 당신은 칩을 소비하거나 더미에 있는 모든 칩과 카드를 가져갑니다. 만약에 칩을 소비하면 턴은 종료됩니다. 카드를 가져가면, 다음 카드가 보여지고 당신의 턴이 계속됩니다.
게임은 마지막 카드가 가져가지면 종료됩니다.
점수 매기기
점수는 카드 숫자에서 당신이 가진 칩의 갯수를 뺀 것의 총합입니다. 하지만, 만약 연속되는 숫자의 카드를 가지고 있다면, 오직 가장 낮은 숫자만 점수에 더해집니다.
예시 : 5개의 칩과 카드 3, 10, 11, 12, 13, 과 20이 있다면, 점수는 3+10+20-5=28 입니다.
가장 낮은 점수를 가진 플레이어가 승자입니다.
0f2ac1d34a613221cf13f38837c2781d9c48266a
1244
1242
2021-01-26T13:49:29Z
Soyounghan09
7197
wikitext
text/x-wiki
개요
노땡스의 목적은 모든 카드가 회수되었을 때 가장 적은 점수를 얻는 플레이어가 되는 것입니다. (보드게임 아레나에선 점수가 부정이라고 합니다.)
준비 <br>
각각의 선수는 11개의 칩을 받습니다. 3~35숫자 카드 중에서 9개의 카드는 랜덤으로 덱에서 제거됩니다. 덱의 맨 윗 카드는 보여집니다.
플레이하기
당신의 턴에, 당신은 칩을 소비하거나 더미에 있는 모든 칩과 카드를 가져갑니다. 만약에 칩을 소비하면 턴은 종료됩니다. 카드를 가져가면, 다음 카드가 보여지고 당신의 턴이 계속됩니다.
게임은 마지막 카드가 가져가지면 종료됩니다.
점수 매기기
점수는 카드 숫자에서 당신이 가진 칩의 갯수를 뺀 것의 총합입니다. 하지만, 만약 연속되는 숫자의 카드를 가지고 있다면, 오직 가장 낮은 숫자만 점수에 더해집니다.
예시 : 5개의 칩과 카드 3, 10, 11, 12, 13, 과 20이 있다면, 점수는 3+10+20-5=28 입니다.
가장 낮은 점수를 가진 플레이어가 승자입니다.
ad7324bcab47d684bbdf5bd9cf3f6baf4743beca
1245
1244
2021-01-26T13:49:51Z
Soyounghan09
7197
wikitext
text/x-wiki
개요
노땡스의 목적은 모든 카드가 회수되었을 때 가장 적은 점수를 얻는 플레이어가 되는 것입니다. (보드게임 아레나에선 점수가 부정이라고 합니다.)
준비 <br>
각각의 선수는 11개의 칩을 받습니다. 3~35숫자 카드 중에서 9개의 카드는 랜덤으로 덱에서 제거됩니다. 덱의 맨 윗 카드는 보여집니다.<br>
플레이하기<br>
당신의 턴에, 당신은 칩을 소비하거나 더미에 있는 모든 칩과 카드를 가져갑니다. 만약에 칩을 소비하면 턴은 종료됩니다. 카드를 가져가면, 다음 카드가 보여지고 당신의 턴이 계속됩니다.
게임은 마지막 카드가 가져가지면 종료됩니다.<br>
점수 매기기<br>
점수는 카드 숫자에서 당신이 가진 칩의 갯수를 뺀 것의 총합입니다. 하지만, 만약 연속되는 숫자의 카드를 가지고 있다면, 오직 가장 낮은 숫자만 점수에 더해집니다.
예시 : 5개의 칩과 카드 3, 10, 11, 12, 13, 과 20이 있다면, 점수는 3+10+20-5=28 입니다.
<br>
<br>
가장 낮은 점수를 가진 플레이어가 승자입니다.
8423249ed2c70012da8fd4fd94d6a32ace9ba154
Gamehelpdingosdreams
0
185
1246
2021-02-16T15:53:04Z
Soyounghan09
7197
새 문서: Dingo and his friends have gotten lost on Walkabout! Visit their dreams to lead them home! <br> 딩고와 그의 친구들이 산책에서 길을 잃어버렸어요! 그들의 꿈에...
wikitext
text/x-wiki
Dingo and his friends have gotten lost on Walkabout! Visit their dreams to lead them home!
<br> 딩고와 그의 친구들이 산책에서 길을 잃어버렸어요! 그들의 꿈에 방문해서 집으로 데려가주세요!
<br> <br>
Each turn consists of two steps performed in order:
각각의 턴은 순서대로 2개의 단계로 구성됩니다.<br>
Walkabout (automatic) 산책(자동)<br>
Dreamtime (player action) 꿈 (플레이어 행동)<br> <br>
CONTENTS<br> 내용<br>
1 Walkabout (Automatic)<br>1. 산책(자동)<br>
2 Dreamtime (Player Action) 2. 꿈(플레이어 행동) <br>
3 Goal <br> 목표
4 Game Variants <br> 변형
4.1 Hazards <br> 어려운 모드
4.2 Easy <br> 쉬운 모드
4.3 Dream Companions <br> 꿈 동행자
4.4 Deep Sleep <br> 깊은 수면<br>
WALKABOUT (AUTOMATIC)
A walkabout card is revealed at random from the deck. The tile in the grid (or the extra tile) with the corresponding landscape (border + picture combination) is automatically flipped over, and your animal is revealed in the location.
<br> 산책 (자동)<br> 덱에서 랜덤으로 산책 카드가 드러납니다. <br> 격자무늬에서
DREAMTIME (PLAYER ACTION)
You click/tap on one of the positions at the edge of the dreamscape grid. This causes the extra tile to slide into the corresponding row or column, thereby shifting the entire row or column of tiles. A new, different tile emerges from the opposite side, to be used for your next action.
GOAL
Be the first player to have your animal revealed in all the locations in the grid matching the marks (spirals) in the Dream Card. This earns you one Victory Point. Play is repeated with a reset grid and a new Dream Card every time, until one player achieves the set number of Victory Points (1, 2, 3 or 4), and claims the final victory.
(Also refer to the Deep Sleep variant below)
GAME VARIANTS
Hazards
If hazards are turned on, there's an extra goal in addition to the usual goal, for you to earn a victory card: Your animal should NOT be present in the hazard locations - those corresponding to the brown markers in the Dream Card.
Easy
In this difficulty setting, suitable for beginners or very young children, you only need to make your animal appear in five locations in a line - either in a row, in a column or along a diagonal.
Dream Companions
If Dream Companions are turned on, there's an extra companion animal tile provided to each player. This adds an additional challenge to the usual goal: Your companion animal should be present in the central location on the grid before you can earn a victory card.
Deep Sleep
In this variant, play three times. At the end of each play, each player is scored as follows:
+1 point per match: Animal on a marked location as in the Dream Card
-1 point per match: Animal on a hazard location as in the Dream Card
+1 point: Companion positioned in the central location
+3 points: Being the first to achieve the goal (considering marks, hazards & companion)
At the end of the third play, the player with the highest total score claims victory!
e801b2f006ba60be715bf65c49724b9b66f6ede0
Gamehelpbandido
0
186
1247
2021-05-04T13:57:17Z
Newt1
7338
새 문서: ▷ 게임 목표 : 팀원들과 협력해서 반디도가 파놓은 모든 탈출구를 막으면 승리! 카드가 모두 떨어졌는데 탈출구가 한개라도 남아있다면...
wikitext
text/x-wiki
▷ 게임 목표 : 팀원들과 협력해서 반디도가 파놓은 모든 탈출구를 막으면 승리! 카드가 모두 떨어졌는데 탈출구가 한개라도 남아있다면 여러분이 패배하고, 반디도가 승리하게됩니다.
▷ 게임 방법
게임 진행은 크게 3단계로 구분됩니다.
1. 기존 카드에 연결되는 카드 1장 내려놓기
2. 만약 자연스럽게 내려 놓을 수 있는 카드가 1장도 존재하지 않는다면 카드를 모두 버린 후 새로운 카드로 3장 보충하기
3. 카드를 보충하여 손에 항상 카드를 3장으로 유지시키기
1. 한명씩 돌아가면서 손에 들고있는 3장의 카드 중 반디도가 파 놓은 탈출구에 자연스럽게 연결이 되도록 이어 놓습니다.
※ 카드를 내려놓을 때 내 손에 들고 있는 카드의 정보를 공유하지 않고 진행을 해야합니다. 단, "어디는 안 건들였으면 좋겠어"라든지, "여긴 내가 막을께" 등으로 어떤 카드를 사용할 건지 대략적으로 말하는 것은 가능합니다.
☆☆터널배치규칙 : 카드를 놓을 때, 터널이 도중에 끊어지도록 놓을 수 없습니다.
2. 만약 내려놓을 수있는 카드가 1장도 존재하지 않는다면 기존에 손에 들고 있는 카드 3장을 모두 카드더미 아래 버린 후 제일 위에서부터 3장을 가져간 후 차례를 마칩니다.
- 내고 싶지 않다고 해서 안낼수 없습니다. 내려놓을 수 있는 카드가 한장이라도 존재한다면 무조건 그 카드를 내려놓아야합니다.
3. 카드를 사용한 플레이어의 경우에는 손에 2장만 가지게 되므로, 카드더미에서 새로운 카드 1장을 보충 받아 손에는 항상 카드가 3장이 되게 합니다.
- 카드더미에 카드가 다 떨어졌다면 보충받지 않은채로 게임을 진행합니다.
(승리) 만약 누군가의 차례에 반디도가 파놓은 탈출구가 모두 막히게 된다면 즉시 게임은 종료되며 여러분이 승리하게 됩니다.
(패배) 사용할 수 있는 카드가 모두 떨어지면 게임은 종료되며 반디도가 파놓은 탈출구가 1곳이라도 남아있다면 여러분은 패배하게 되며, 반디도가 최종 승리자가 됩니다.
출처: https://m.blog.naver.com/jurong25/221444171701
b8da96c2048ba1fd341ce3058d1bb4e75707f6e9
Gamehelpcardiceo
0
187
1248
2021-06-28T20:41:49Z
KiMRyhHwan
7396
뭐지이게
wikitext
text/x-wiki
이게 무슨게임인지 빨리 한국어로 번역해주세요 뭐야 이게
c3465ecc1ff4e749670b804c865c22e1ad2de567
Gamehelpgrandbazaar
0
188
1249
2021-07-11T17:21:21Z
Cocaincola
7411
새 문서: Gamehelpgrandbazaar 게임은 비트코인과 유사한 주식게임 입니다. 보석 3종류를 초기자금 30돈으로 각 10에서 시작하는 보석 세가지 종류를 구...
wikitext
text/x-wiki
Gamehelpgrandbazaar 게임은 비트코인과 유사한 주식게임 입니다.
보석 3종류를 초기자금 30돈으로 각 10에서 시작하는 보석 세가지 종류를 구매하고 추후에
보석을 구매할때는 자금이 있거나 자금이 없다면 무조건 보석을 팔아서 다른 보석을 사야합니다 보석만 팔수는 없습니다.
제일 많은 이익을 가져가는 사람이 승리입니다. 보석을 구매할때 보석금액 + 보유금액 합쳐서 구매가 가능합니다.
총27턴이며 카드는 자동으로 한턴이 끝날때 마다 넘어갑니다.
7e6999633b7d11653a0e48e0e866083169428481
Gamehelppandemic
0
189
1250
2021-07-14T02:22:11Z
Spian
7416
기본 설명 추가, 게임이 자동으로 처리하는 부분은 생략, 미비한 부분 추가바랍니다.
wikitext
text/x-wiki
팬데믹은 전 지구를 휩쓸고 있는 4개의 질병에 대항하는 영웅들의 이야기입니다!
1. 게임의 종료
- 아래의 경우 플레이어들은 승리합니다.
* 4개의 질병에 대한 치료제를 개발 하면 플레이어들의 승리입니다.
- 아래의 경우 플레이어들은 패배합니다.
* 질병 토큰을 추가해야 할 때 해당 질병 토큰이 부족할 경우
* 카드를 뽑아야 할 때 뽑을 카드가 부족할 경우
* 확산 마커가 마지막에 닿을 경우
2. 차례 진행 순서
- 원하는 순서대로 4개의 행동을 수행
- 카드 2장 뽑기
* 전염 카드가 나온다면 전염 카드의 내용 즉시 수행
- 감염 카드를 감염 단계에 따라 뽑고 질병 토큰 추가
3. 행동
- 이동: 선으로 연결된 도시와 도시 사이를 이동
- 비행: 이동을 원하는 도시 카드를 사용하여 해당 도시로 이동
- 전용기 이용: 현재 도시와 같은 도시 카드를 사용하여 원하는 도시로 이동
- 정기 항공편 이용 : 연구소에서 다른 연구소로 이동
- 질병 치료: 현재 위치한 도시에 있는 질병 토큰 1개를 제거
- 정보 공유: 현재 위치한 도시에 있는 다른 플레이어와 현재 위치의 도시 카드를 주기/받기
- 연구소 건설: 현재 도시와 같은 도시 카드를 사용하여 현재 위치에 연구소 건설 (연구소가 부족하면 기존 연구소를 현재 위치로 이동)
- 치료제 개발: 연구소에서 같은 색상의 도시 카드 5장을 사용하여 해당 색상 질병의 치료제 개발
4. 치료제 개발 보너스
- 치료제가 개발되면 현재 위치에 있는 모든 해당 색상 질병을 한번의 행동으로 제거 가능
- 치료제가 개발된 질병 토큰이 보드에서 모두 제거되면 해당 질병은 근절이 되어 더 이상 추가되지 않음
5. 이벤트 카드
- 이벤트 카드 사용은 행동이 소모되지 않음
- 이벤트 카드는 본인의 차례가 아니어도 사용할 수 있음
6. 카드 소지 제한
- 카드는 언제나 7장까지만 가지고 있을 수 있음
- 8장을 넘게 갖게 되면 즉시 카드가 7장이 되게 버려야 함
- 이 때, 사용 가능한 이벤트 카드가 있다면 사용하여 손의 카드를 줄일 수 있음
7. 게임 팁
- 전염 카드가 나올 때마다 버려진 감염 카드가 감염 더미의 위로 다시 추가됩니다. 즉, 기존에 질병이 발병한 곳 위주로 질병이 추가되기 때문에 나왔던 도시를 파악하는 것이 중요합니다.
- 게임의 승리 조건은 치료제를 4개 개발하는 것 뿐입니다. 한 명의 플레이어가 같은 색의 도시 카드 5장을 모으는 것이 가장 중요합니다.
- 같은 위치에 있는 두 플레이어가 해당하는 도시의 카드만 교환할 수 있음을 명심해야 합니다.
- 자신의 캐릭터 능력을 십분 발휘해야만 합니다.
e75c9f94e5c21491475a62b1d07deb59f42adece
Tips reversi
0
190
1251
2021-07-21T11:05:15Z
MarlangRicecake
7426
오델로/리버시 전략
wikitext
text/x-wiki
처음부터 최대한 많이 따려고만 하면 지기 십상입니다.
게임의 목표는 이동 가능성을 유지하는 것, 즉 놓을 수 있는 자리를 최대한 많이 보유하는 것입니다. 이를 위해선 간단히 당신의 돌을 최소화하고 상대의 돌을 최대화하면 됩니다. 이를 통해 다양한 선택지를 마련할 수 있을 것입니다.
이는 상대가 원치 않는 곳에 돌을 놓으라고 유도하기 위해서입니다. 이를 테면 당신에게 판의 꼭짓점을 내어주는 등이죠. 꼭짓점은 한 번 보유하면 뺏을 수 없기 때문에 돌 수를 확보하기도, 유지하기도 좋은 지점입니다.
물론 둘 다 해당 전략을 사용하고 있다면 둘 중 더 뛰어난 사람이 이기겠죠. 오델로/리버시 게임의 전략은 이때부터 드러납니다.
또다른 전략들을 보고 싶다면 이 링크를 클릭하세요. www.youtube.com/othellolessons
c4fdaeaa184c098883e16b391e20ae952c4d559a
Gamehelphomesteaders
0
191
1252
2021-08-12T23:05:44Z
Ananstarsha
7468
새 문서: 홈스테더스는 플레이어가 토지에 입찰하고 건물을 개발하는 경매 및 자원 관리 게임입니다. 게임은 10라운드로 진행됩니다. 게임이 끝나...
wikitext
text/x-wiki
홈스테더스는 플레이어가 토지에 입찰하고 건물을 개발하는 경매 및 자원 관리 게임입니다.
게임은 10라운드로 진행됩니다. 게임이 끝나면 최종 수입 및 득점 라운드(대출을 상환할 수 있는 곳)가 있습니다.
각 라운드에는 3단계가 있습니다.
설정: 건물 및 경매 타일이 업데이트되는 곳(필요한 경우)
수입 단계: 플레이어가 자원을 획득하는 단계
경매 단계: 플레이어가 사용 가능한 토지에 입찰한 다음 해당 토지에 건물을 개발하기 위해 자원을 사용합니다.
내용물
1 설정
2 소득
3 경매
4 빌드
설정
현재 라운드의 경매 타일이 공개됩니다.
입찰 토큰은 보드에서 제거됩니다.
라운드 5와 9에서는 건물 재고도 업데이트됩니다.
새로운 건물을 사용할 수 있습니다
기존 건물은 더 이상 사용할 수 없습니다.
소득
플레이어는 건물에 일꾼을 할당합니다.
완료되면 건물에서 수입을 얻습니다.
그러면 그들은 노동자들에게 돈을 지불해야 할 것입니다.
일꾼당 은화 1개 또는 최대 5명의 일꾼에게 지급하는 금 1개
경매
첫 번째 플레이어 타일을 가진 플레이어부터 시작하여,
플레이어는 사용 가능한 경매 또는 패스 중 하나에 입찰합니다.
입찰 플레이어가 다른 플레이어보다 높은 입찰가를 제시하거나 경매에서 초기 입찰을 해야 하는 경우(어떤 값이든)
통과하면 더 이상 라운드에서 입찰할 수 없으며 대신 무료로 철도 트랙을 전진시킬 수 있습니다(보너스를 받습니다).
입찰가보다 높은 플레이어는 입찰 또는 통과할 수 있는 또 다른 기회를 얻게 됩니다(그리고 보너스를 받을 수 있음).
이것은 모든 플레이어가 경매에서 이기거나 통과할 때까지 계속됩니다.
빌드
첫 번째 경매부터 시작하여 승자(있는 경우)
첫 번째 경매의 승자는 다음 라운드의 첫 번째 플레이어 토큰도 받습니다.
그들은 은이나 금을 사용하여 입찰가를 지불할 것입니다.
그런 다음 건설할 건물(경매에 건물이 있는 경우)을 선택할 수 있습니다.
경매에 보너스가 있는 경우 보너스를 받을 수 있습니다.
참고: 빌드는 경매 순서로 이루어지고 건물 재고가 제한되어 있으므로 빌드 순서가 매우 중요할 수 있습니다.
934b52eac4739728c3f43ff97536d926fb6ed2f8
1258
1252
2021-08-12T23:18:44Z
Ananstarsha
7468
wikitext
text/x-wiki
홈스테더스는 플레이어가 토지에 입찰하고 건물을 개발하는 경매 및 자원 관리 게임입니다.
게임은 10라운드로 진행됩니다. 게임이 끝나면 최종 수입 및 득점 라운드(대출을 상환할 수 있는 곳)가 있습니다.
각 라운드에는 3단계가 있습니다.
설정: 건물 및 경매 타일이 업데이트되는 곳(필요한 경우)
수입 단계: 플레이어가 자원을 획득하는 단계
경매 단계: 플레이어가 사용 가능한 토지에 입찰한 다음 해당 토지에 건물을 개발하기 위해 자원을 사용합니다.
내용물
1 설정
2 소득
3 경매
4 빌드
설정
현재 라운드의 경매 타일이 공개됩니다.
입찰 토큰은 보드에서 제거됩니다.
라운드 5와 9에서는 건물 재고도 업데이트됩니다.
새로운 건물을 사용할 수 있습니다
기존 건물은 더 이상 사용할 수 없습니다.
소득
플레이어는 건물에 일꾼을 할당합니다.
완료되면 건물에서 수입을 얻습니다.
그러면 그들은 노동자들에게 돈을 지불해야 할 것입니다.
일꾼당 은화 1개 또는 최대 5명의 일꾼에게 지급하는 금 1개
경매
첫 번째 플레이어 타일을 가진 플레이어부터 시작하여,
플레이어는 사용 가능한 경매 또는 패스 중 하나에 입찰합니다.
입찰 플레이어가 다른 플레이어보다 높은 입찰가를 제시하거나 경매에서 초기 입찰을 해야 하는 경우(어떤 값이든)
통과하면 더 이상 라운드에서 입찰할 수 없으며 대신 무료로 철도 트랙을 전진시킬 수 있습니다(보너스를 받습니다).
입찰가보다 높은 플레이어는 입찰 또는 통과할 수 있는 또 다른 기회를 얻게 됩니다(그리고 보너스를 받을 수 있음).
이것은 모든 플레이어가 경매에서 이기거나 통과할 때까지 계속됩니다.
빌드
첫 번째 경매부터 시작하여 승자(있는 경우)
첫 번째 경매의 승자는 다음 라운드의 첫 번째 플레이어 토큰도 받습니다.
그들은 은이나 금을 사용하여 입찰가를 지불할 것입니다.
그런 다음 건설할 건물(경매에 건물이 있는 경우)을 선택할 수 있습니다.
경매에 보너스가 있는 경우 보너스를 받을 수 있습니다.
참고: 빌드는 경매 순서로 이루어지고 건물 재고가 제한되어 있으므로 빌드 순서가 매우 중요할 수 있습니다.
393a36a412b88f829f37cf29696c2abc32faf2ab
Gamehelppuertorico
0
23
1253
1085
2021-08-12T23:11:57Z
Ananstarsha
7468
/* Goal */
wikitext
text/x-wiki
목표
다음을 수집하여 게임 종료 시 가장 많은 승점을 얻은 플레이어가 되십시오.
건물 승리 점수
캡틴 단계에서 획득한 승점 토큰
점유된 대형 건물에 대해 게임 종료 시 획득한 조건부 승점
동점일 경우, 가장 많은 금화와 상품을 소유한 플레이어가 승자가 됩니다
== Rules summary ==
The game is played over several rounds.
At the start of a round, the governor selects a role, then each player in turn selects a role.
At the end of the round, the governor token moves to the next player.
When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege.
Available roles are the following:
* Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations.
* Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations.
* Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet.
* Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available.
* Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available.
* Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship.
* Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none.
Please also note that occupied violet buildings have modifier effects for role actions.
End of game happens at the end of the round for which one of the following events comes to pass :
* there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase
* the last victory point token has been earned during the captain phase
* at least one of the players built on his 12th and last free space in the city.
== Playing online ==
Choosing a role : click on the role of your choice in the list on the right of your game board.
* Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page).
* Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege.
* Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel.
* Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated.
* Builder role : click on the building that you want to buy. Placement on your board is automated.
* Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame.
* Prospector role : doubloon is earned immediately.
Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse.
== 'Balanced game' variant ==
This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page].
* The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons
* Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
28de1e5ac12e1667ba27c4efc4686d6f8cd9501f
1254
1253
2021-08-12T23:13:07Z
Ananstarsha
7468
/* Rules summary */
wikitext
text/x-wiki
목표
다음을 수집하여 게임 종료 시 가장 많은 승점을 얻은 플레이어가 되십시오.
건물 승리 점수
캡틴 단계에서 획득한 승점 토큰
점유된 대형 건물에 대해 게임 종료 시 획득한 조건부 승점
동점일 경우, 가장 많은 금화와 상품을 소유한 플레이어가 승자가 됩니다
규칙 요약
게임은 여러 라운드에 걸쳐 진행됩니다. 라운드 시작 시 주지사가 역할을 선택한 다음 각 플레이어가 차례로 역할을 선택합니다. 라운드가 끝나면 주지사 토큰이 다음 플레이어에게 이동합니다.
역할이 선택되면 각 플레이어는 차례로 이 역할에 대한 행동을 합니다. 역할을 선택한 플레이어만 역할 권한을 사용할 수 있습니다.
사용 가능한 역할은 다음과 같습니다.
시장: 식민지 개척자들이 새로운 세계에 발을 들였습니다! 특권: 시장은 공급에서 식민지 주민을 한 명 더 얻을 수 있습니다. 행동: 차례로 시장부터 시작하여 플레이어는 배가 비어 있을 때까지 배에서 식민지 주민 한 명을 얻습니다. 그런 다음 플레이어는 건물과 농장에 식민자를 설정해야 합니다.
장인: 상품이 생산됩니다. 특권 : 장인은 자신이 선택한 재화를 하나 더 생산할 수 있습니다. 행동: 점령한 건물과 농장을 위한 상품을 생산하세요.
상인: 상품을 거래처에 판매합니다. 특권: 상인은 판매하면 1금화를 추가로 얻습니다. 행동 : 무역회사가 아직 가지고 있지 않은 재화 하나를 판매하십시오.
정착민 : 플랜테이션 정착. 특권 : 정착민은 농장 대신 채석장을 얻을 수 있습니다. 행동: 사용 가능한 농장 중에서 선택한 농장을 얻습니다.
건축업자 : 건물을 사고 건축합니다. 특전 : 건축업자는 정가보다 1금화 저렴하게 건물을 지을 수 있습니다. 행동: 사용 가능한 건물 중에서 선택하십시오.
선장 : 구세계로 물품을 배송하여 승점을 얻습니다. 특전: 선장은 물품을 선적하면 승점 1점을 추가로 얻습니다. 조치: 화물선에 적재할 상품 유형을 선택하십시오. 배에 실린 이러한 유형의 상품 배럴당 승점 1점을 얻습니다.
프로스펙터: 골드러시는 돈을 가져온다! 특권: 채굴자는 은행에서 1금화를 얻습니다. 조치: 없음.
또한 점령된 보라색 건물에는 역할 행동에 대한 수정 효과가 있습니다.
게임 종료는 다음 이벤트 중 하나가 발생하는 라운드가 끝날 때 발생합니다.
시장 단계가 끝날 때 식민지 배를 다시 채울 충분한 식민지 주민이 공급되지 않습니다.
캡틴 단계에서 마지막 승점 토큰을 획득했습니다.
플레이어 중 적어도 한 명이 도시의 12번째이자 마지막 여유 공간에 건설했습니다.
== Playing online ==
Choosing a role : click on the role of your choice in the list on the right of your game board.
* Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page).
* Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege.
* Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel.
* Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated.
* Builder role : click on the building that you want to buy. Placement on your board is automated.
* Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame.
* Prospector role : doubloon is earned immediately.
Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse.
== 'Balanced game' variant ==
This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page].
* The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons
* Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
3a899b7d9d04b803bc29981ed53034cb23b3ae25
1255
1254
2021-08-12T23:15:22Z
Ananstarsha
7468
/* Rules summary */
wikitext
text/x-wiki
목표
다음을 수집하여 게임 종료 시 가장 많은 승점을 얻은 플레이어가 되십시오.
건물 승리 점수
캡틴 단계에서 획득한 승점 토큰
점유된 대형 건물에 대해 게임 종료 시 획득한 조건부 승점
동점일 경우, 가장 많은 금화와 상품을 소유한 플레이어가 승자가 됩니다
규칙 요약
게임은 여러 라운드에 걸쳐 진행됩니다. 라운드 시작 시 주지사가 역할을 선택한 다음 각 플레이어가 차례로 역할을 선택합니다. 라운드가 끝나면 주지사 토큰이 다음 플레이어에게 이동합니다.
역할이 선택되면 각 플레이어는 차례로 이 역할에 대한 행동을 합니다. 역할을 선택한 플레이어만 역할 권한을 사용할 수 있습니다.
사용 가능한 역할은 다음과 같습니다.
시장: 식민지 개척자들이 새로운 세계에 발을 들였습니다! 특권: 시장은 공급에서 식민지 주민을 한 명 더 얻을 수 있습니다. 행동: 차례로 시장부터 시작하여 플레이어는 배가 비어 있을 때까지 배에서 식민지 주민 한 명을 얻습니다. 그런 다음 플레이어는 건물과 농장에 식민자를 설정해야 합니다.
장인: 상품이 생산됩니다. 특권 : 장인은 자신이 선택한 재화를 하나 더 생산할 수 있습니다. 행동: 점령한 건물과 농장을 위한 상품을 생산하세요.
상인: 상품을 거래처에 판매합니다. 특권: 상인은 판매하면 1금화를 추가로 얻습니다. 행동 : 무역회사가 아직 가지고 있지 않은 재화 하나를 판매하십시오.
정착민 : 플랜테이션 정착. 특권 : 정착민은 농장 대신 채석장을 얻을 수 있습니다. 행동: 사용 가능한 농장 중에서 선택한 농장을 얻습니다.
건축업자 : 건물을 사고 건축합니다. 특전 : 건축업자는 정가보다 1금화 저렴하게 건물을 지을 수 있습니다. 행동: 사용 가능한 건물 중에서 선택하십시오.
선장 : 구세계로 물품을 배송하여 승점을 얻습니다. 특전: 선장은 물품을 선적하면 승점 1점을 추가로 얻습니다. 조치: 화물선에 적재할 상품 유형을 선택하십시오. 배에 실린 이러한 유형의 상품 배럴당 승점 1점을 얻습니다.
프로스펙터: 골드러시는 돈을 가져온다! 특권: 채굴자는 은행에서 1금화를 얻습니다. 조치: 없음.
또한 점령된 보라색 건물에는 역할 행동에 대한 수정 효과가 있습니다.
게임 종료는 다음 이벤트 중 하나가 발생하는 라운드가 끝날 때 발생합니다.
시장 단계가 끝날 때 식민지 배를 다시 채울 충분한 식민지 주민이 공급되지 않습니다.
캡틴 단계에서 마지막 승점 토큰을 획득했습니다.
플레이어 중 적어도 한 명이 도시의 12번째이자 마지막 여유 공간에 건설했습니다.
== Playing online ==
Choosing a role : click on the role of your choice in the list on the right of your game board.
* Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page).
* Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege.
* Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel.
* Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated.
* Builder role : click on the building that you want to buy. Placement on your board is automated.
* Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame.
* Prospector role : doubloon is earned immediately.
Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse.
== 'Balanced game' variant ==
This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page].
* The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons
* Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
0ce7771ec1c82f771f720aecda9032f383311f2b
1256
1255
2021-08-12T23:15:59Z
Ananstarsha
7468
/* Playing online */
wikitext
text/x-wiki
목표
다음을 수집하여 게임 종료 시 가장 많은 승점을 얻은 플레이어가 되십시오.
건물 승리 점수
캡틴 단계에서 획득한 승점 토큰
점유된 대형 건물에 대해 게임 종료 시 획득한 조건부 승점
동점일 경우, 가장 많은 금화와 상품을 소유한 플레이어가 승자가 됩니다
규칙 요약
게임은 여러 라운드에 걸쳐 진행됩니다. 라운드 시작 시 주지사가 역할을 선택한 다음 각 플레이어가 차례로 역할을 선택합니다. 라운드가 끝나면 주지사 토큰이 다음 플레이어에게 이동합니다.
역할이 선택되면 각 플레이어는 차례로 이 역할에 대한 행동을 합니다. 역할을 선택한 플레이어만 역할 권한을 사용할 수 있습니다.
사용 가능한 역할은 다음과 같습니다.
시장: 식민지 개척자들이 새로운 세계에 발을 들였습니다! 특권: 시장은 공급에서 식민지 주민을 한 명 더 얻을 수 있습니다. 행동: 차례로 시장부터 시작하여 플레이어는 배가 비어 있을 때까지 배에서 식민지 주민 한 명을 얻습니다. 그런 다음 플레이어는 건물과 농장에 식민자를 설정해야 합니다.
장인: 상품이 생산됩니다. 특권 : 장인은 자신이 선택한 재화를 하나 더 생산할 수 있습니다. 행동: 점령한 건물과 농장을 위한 상품을 생산하세요.
상인: 상품을 거래처에 판매합니다. 특권: 상인은 판매하면 1금화를 추가로 얻습니다. 행동 : 무역회사가 아직 가지고 있지 않은 재화 하나를 판매하십시오.
정착민 : 플랜테이션 정착. 특권 : 정착민은 농장 대신 채석장을 얻을 수 있습니다. 행동: 사용 가능한 농장 중에서 선택한 농장을 얻습니다.
건축업자 : 건물을 사고 건축합니다. 특전 : 건축업자는 정가보다 1금화 저렴하게 건물을 지을 수 있습니다. 행동: 사용 가능한 건물 중에서 선택하십시오.
선장 : 구세계로 물품을 배송하여 승점을 얻습니다. 특전: 선장은 물품을 선적하면 승점 1점을 추가로 얻습니다. 조치: 화물선에 적재할 상품 유형을 선택하십시오. 배에 실린 이러한 유형의 상품 배럴당 승점 1점을 얻습니다.
프로스펙터: 골드러시는 돈을 가져온다! 특권: 채굴자는 은행에서 1금화를 얻습니다. 조치: 없음.
또한 점령된 보라색 건물에는 역할 행동에 대한 수정 효과가 있습니다.
게임 종료는 다음 이벤트 중 하나가 발생하는 라운드가 끝날 때 발생합니다.
시장 단계가 끝날 때 식민지 배를 다시 채울 충분한 식민지 주민이 공급되지 않습니다.
캡틴 단계에서 마지막 승점 토큰을 획득했습니다.
플레이어 중 적어도 한 명이 도시의 12번째이자 마지막 여유 공간에 건설했습니다.
온라인 플레이
역할 선택: 게임 보드 오른쪽에 있는 목록에서 원하는 역할을 클릭합니다.
시장 역할: 공급에서 추가 식민지를 얻는 것을 수락하거나 거부합니다. 식민지 개척자는 플레이어에 의해 자동으로 모집됩니다. 건물이나 농장을 클릭하여 식민지 주민을 설정하십시오. 식민지 주민을 클릭하여 San Juan으로 다시 보내십시오(San Juan의 식민지 주민 카운터는 페이지 오른쪽의 플레이어 패널에 있습니다).
장인 역할 : 상품 생산이 자동화됩니다(소유 상품 카운터는 페이지 오른쪽의 플레이어 패널에 있습니다). 그런 다음, 당신의 특권으로 생산할 수 있는 한 가지 추가 재화를 선택하십시오.
상인 역할: 플레이어 패널에서 적절한 카운터를 클릭하여 판매하려는 상품을 선택합니다.
정착자 역할 : 원하는 농장(또는 채석장)을 클릭합니다. 보드에 배치가 자동화됩니다.
빌더 역할 : 구매하려는 건물을 클릭합니다. 보드에 배치가 자동화됩니다.
선장 역할: 일부 상품을 선적하려는 화물선을 클릭합니다. 그런 다음 플레이어 패널에서 적절한 카운터를 클릭하여 배송하려는 상품 유형을 선택합니다. 선장 단계가 끝나면 보관할 물품(창고 또는 윈드로즈)이 있는 경우 해당 카운터를 클릭합니다. 저장된 상품은 빨간색 프레임으로 강조 표시됩니다.
탐사자 역할 : 즉시 금화를 얻습니다.
툴팁은 마우스로 게임 요소를 가리켜 역할과 건물에 대한 정보를 제공하는 데 사용할 수 있습니다.
== 'Balanced game' variant ==
This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page].
* The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons
* Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
02485f0ab0672ea0e6badca09e03fd673293e495
1257
1256
2021-08-12T23:16:43Z
Ananstarsha
7468
/* 'Balanced game' variant */
wikitext
text/x-wiki
목표
다음을 수집하여 게임 종료 시 가장 많은 승점을 얻은 플레이어가 되십시오.
건물 승리 점수
캡틴 단계에서 획득한 승점 토큰
점유된 대형 건물에 대해 게임 종료 시 획득한 조건부 승점
동점일 경우, 가장 많은 금화와 상품을 소유한 플레이어가 승자가 됩니다
규칙 요약
게임은 여러 라운드에 걸쳐 진행됩니다. 라운드 시작 시 주지사가 역할을 선택한 다음 각 플레이어가 차례로 역할을 선택합니다. 라운드가 끝나면 주지사 토큰이 다음 플레이어에게 이동합니다.
역할이 선택되면 각 플레이어는 차례로 이 역할에 대한 행동을 합니다. 역할을 선택한 플레이어만 역할 권한을 사용할 수 있습니다.
사용 가능한 역할은 다음과 같습니다.
시장: 식민지 개척자들이 새로운 세계에 발을 들였습니다! 특권: 시장은 공급에서 식민지 주민을 한 명 더 얻을 수 있습니다. 행동: 차례로 시장부터 시작하여 플레이어는 배가 비어 있을 때까지 배에서 식민지 주민 한 명을 얻습니다. 그런 다음 플레이어는 건물과 농장에 식민자를 설정해야 합니다.
장인: 상품이 생산됩니다. 특권 : 장인은 자신이 선택한 재화를 하나 더 생산할 수 있습니다. 행동: 점령한 건물과 농장을 위한 상품을 생산하세요.
상인: 상품을 거래처에 판매합니다. 특권: 상인은 판매하면 1금화를 추가로 얻습니다. 행동 : 무역회사가 아직 가지고 있지 않은 재화 하나를 판매하십시오.
정착민 : 플랜테이션 정착. 특권 : 정착민은 농장 대신 채석장을 얻을 수 있습니다. 행동: 사용 가능한 농장 중에서 선택한 농장을 얻습니다.
건축업자 : 건물을 사고 건축합니다. 특전 : 건축업자는 정가보다 1금화 저렴하게 건물을 지을 수 있습니다. 행동: 사용 가능한 건물 중에서 선택하십시오.
선장 : 구세계로 물품을 배송하여 승점을 얻습니다. 특전: 선장은 물품을 선적하면 승점 1점을 추가로 얻습니다. 조치: 화물선에 적재할 상품 유형을 선택하십시오. 배에 실린 이러한 유형의 상품 배럴당 승점 1점을 얻습니다.
프로스펙터: 골드러시는 돈을 가져온다! 특권: 채굴자는 은행에서 1금화를 얻습니다. 조치: 없음.
또한 점령된 보라색 건물에는 역할 행동에 대한 수정 효과가 있습니다.
게임 종료는 다음 이벤트 중 하나가 발생하는 라운드가 끝날 때 발생합니다.
시장 단계가 끝날 때 식민지 배를 다시 채울 충분한 식민지 주민이 공급되지 않습니다.
캡틴 단계에서 마지막 승점 토큰을 획득했습니다.
플레이어 중 적어도 한 명이 도시의 12번째이자 마지막 여유 공간에 건설했습니다.
온라인 플레이
역할 선택: 게임 보드 오른쪽에 있는 목록에서 원하는 역할을 클릭합니다.
시장 역할: 공급에서 추가 식민지를 얻는 것을 수락하거나 거부합니다. 식민지 개척자는 플레이어에 의해 자동으로 모집됩니다. 건물이나 농장을 클릭하여 식민지 주민을 설정하십시오. 식민지 주민을 클릭하여 San Juan으로 다시 보내십시오(San Juan의 식민지 주민 카운터는 페이지 오른쪽의 플레이어 패널에 있습니다).
장인 역할 : 상품 생산이 자동화됩니다(소유 상품 카운터는 페이지 오른쪽의 플레이어 패널에 있습니다). 그런 다음, 당신의 특권으로 생산할 수 있는 한 가지 추가 재화를 선택하십시오.
상인 역할: 플레이어 패널에서 적절한 카운터를 클릭하여 판매하려는 상품을 선택합니다.
정착자 역할 : 원하는 농장(또는 채석장)을 클릭합니다. 보드에 배치가 자동화됩니다.
빌더 역할 : 구매하려는 건물을 클릭합니다. 보드에 배치가 자동화됩니다.
선장 역할: 일부 상품을 선적하려는 화물선을 클릭합니다. 그런 다음 플레이어 패널에서 적절한 카운터를 클릭하여 배송하려는 상품 유형을 선택합니다. 선장 단계가 끝나면 보관할 물품(창고 또는 윈드로즈)이 있는 경우 해당 카운터를 클릭합니다. 저장된 상품은 빨간색 프레임으로 강조 표시됩니다.
탐사자 역할 : 즉시 금화를 얻습니다.
툴팁은 마우스로 게임 요소를 가리켜 역할과 건물에 대한 정보를 제공하는 데 사용할 수 있습니다.
'균형잡힌 게임' 변형
이 변형은 푸에르토리코(보드 게임) Wikipedia 페이지에 나열된 대로 각 플레이어에게 동일한 승리 기회를 제공하는 두 가지 게임 밸런스 수정을 구현합니다.
공장과 대학 건물의 가격이 교환되어 공장 비용은 8금화, 대학 비용은 7금화입니다.
옥수수 농장으로 시작하는 플레이어는 인디고 농장으로 시작하는 플레이어보다 1금화 적게 가지고 시작합니다.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
cdbfc2416d4ba7814d69051ecf4f0f3f43ee35d8
1265
1257
2021-08-13T00:47:28Z
Ananstarsha
7468
wikitext
text/x-wiki
목표
다음을 수집하여 게임 종료 시 가장 많은 승점을 얻은 플레이어가 되십시오.
건물 승리 점수
캡틴 단계에서 획득한 승점 토큰
점유된 대형 건물에 대해 게임 종료 시 획득한 조건부 승점
동점일 경우, 가장 많은 금화와 상품을 소유한 플레이어가 승자가 됩니다
규칙 요약
게임은 여러 라운드에 걸쳐 진행됩니다. 라운드 시작 시 주지사가 역할을 선택한 다음 각 플레이어가 차례로 역할을 선택합니다. 라운드가 끝나면 주지사 토큰이 다음 플레이어에게 이동합니다.
역할이 선택되면 각 플레이어는 차례로 이 역할에 대한 행동을 합니다. 역할을 선택한 플레이어만 역할 권한을 사용할 수 있습니다.
사용 가능한 역할은 다음과 같습니다.
시장: 식민지 개척자들이 새로운 세계에 발을 들였습니다! 특권: 시장은 공급에서 식민지 주민을 한 명 더 얻을 수 있습니다. 행동: 차례로 시장부터 시작하여 플레이어는 배가 비어 있을 때까지 배에서 식민지 주민 한 명을 얻습니다. 그런 다음 플레이어는 건물과 농장에 식민자를 설정해야 합니다.
장인: 상품이 생산됩니다. 특권 : 장인은 자신이 선택한 재화를 하나 더 생산할 수 있습니다. 행동: 점령한 건물과 농장을 위한 상품을 생산하세요.
상인: 상품을 거래처에 판매합니다. 특권: 상인은 판매하면 1금화를 추가로 얻습니다. 행동 : 무역회사가 아직 가지고 있지 않은 재화 하나를 판매하십시오.
정착민 : 플랜테이션 정착. 특권 : 정착민은 농장 대신 채석장을 얻을 수 있습니다. 행동: 사용 가능한 농장 중에서 선택한 농장을 얻습니다.
건축업자 : 건물을 사고 건축합니다. 특전 : 건축업자는 정가보다 1금화 저렴하게 건물을 지을 수 있습니다. 행동: 사용 가능한 건물 중에서 선택하십시오.
선장 : 구세계로 물품을 배송하여 승점을 얻습니다. 특전: 선장은 물품을 선적하면 승점 1점을 추가로 얻습니다. 조치: 화물선에 적재할 상품 유형을 선택하십시오. 배에 실린 이러한 유형의 상품 배럴당 승점 1점을 얻습니다.
프로스펙터: 골드러시는 돈을 가져온다! 특권: 채굴자는 은행에서 1금화를 얻습니다. 조치: 없음.
또한 점령된 보라색 건물에는 역할 행동에 대한 수정 효과가 있습니다.
게임 종료는 다음 이벤트 중 하나가 발생하는 라운드가 끝날 때 발생합니다.
시장 단계가 끝날 때 식민지 배를 다시 채울 충분한 식민지 주민이 공급되지 않습니다.
캡틴 단계에서 마지막 승점 토큰을 획득했습니다.
플레이어 중 적어도 한 명이 도시의 12번째이자 마지막 여유 공간에 건설했습니다.
온라인 플레이
역할 선택: 게임 보드 오른쪽에 있는 목록에서 원하는 역할을 클릭합니다.
시장 역할: 공급에서 추가 식민지를 얻는 것을 수락하거나 거부합니다. 식민지 개척자는 플레이어에 의해 자동으로 모집됩니다. 건물이나 농장을 클릭하여 식민지 주민을 설정하십시오. 식민지 주민을 클릭하여 San Juan으로 다시 보내십시오(San Juan의 식민지 주민 카운터는 페이지 오른쪽의 플레이어 패널에 있습니다).
장인 역할 : 상품 생산이 자동화됩니다(소유 상품 카운터는 페이지 오른쪽의 플레이어 패널에 있습니다). 그런 다음, 당신의 특권으로 생산할 수 있는 한 가지 추가 재화를 선택하십시오.
상인 역할: 플레이어 패널에서 적절한 카운터를 클릭하여 판매하려는 상품을 선택합니다.
정착자 역할 : 원하는 농장(또는 채석장)을 클릭합니다. 보드에 배치가 자동화됩니다.
빌더 역할 : 구매하려는 건물을 클릭합니다. 보드에 배치가 자동화됩니다.
선장 역할: 일부 상품을 선적하려는 화물선을 클릭합니다. 그런 다음 플레이어 패널에서 적절한 카운터를 클릭하여 배송하려는 상품 유형을 선택합니다. 선장 단계가 끝나면 보관할 물품(창고 또는 윈드로즈)이 있는 경우 해당 카운터를 클릭합니다. 저장된 상품은 빨간색 프레임으로 강조 표시됩니다.
탐사자 역할 : 즉시 금화를 얻습니다.
툴팁은 마우스로 게임 요소를 가리켜 역할과 건물에 대한 정보를 제공하는 데 사용할 수 있습니다.
'균형잡힌 게임' 변형
이 변형은 푸에르토리코(보드 게임) Wikipedia 페이지에 나열된 대로 각 플레이어에게 동일한 승리 기회를 제공하는 두 가지 게임 밸런스 수정을 구현합니다.
공장과 대학 건물의 가격이 교환되어 공장 비용은 8금화, 대학 비용은 7금화입니다.
옥수수 농장으로 시작하는 플레이어는 인디고 농장으로 시작하는 플레이어보다 1금화 적게 가지고 시작합니다.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
bd0bc8f0e9656c264c543091ce09ca3f46a41e07
1266
1265
2021-08-13T01:00:08Z
Ananstarsha
7468
wikitext
text/x-wiki
목표
다음을 수집하여 게임 종료 시 가장 많은 승점을 얻은 플레이어가 되십시오.
건물 승리 점수
캡틴 단계에서 획득한 승점 토큰
점유된 대형 건물에 대해 게임 종료 시 획득한 조건부 승점
동점일 경우, 가장 많은 금화와 상품을 소유한 플레이어가 승자가 됩니다
규칙 요약
게임은 여러 라운드에 걸쳐 진행됩니다. 라운드 시작 시 주지사가 역할을 선택한 다음 각 플레이어가 차례로 역할을 선택합니다. 라운드가 끝나면 주지사 토큰이 다음 플레이어에게 이동합니다.
역할이 선택되면 각 플레이어는 차례로 이 역할에 대한 행동을 합니다. 역할을 선택한 플레이어만 역할 권한을 사용할 수 있습니다.
사용 가능한 역할은 다음과 같습니다.
시장: 식민지 개척자들이 새로운 세계에 발을 들였습니다! 특권: 시장은 공급에서 식민지 주민을 한 명 더 얻을 수 있습니다. 행동: 차례로 시장부터 시작하여 플레이어는 배가 비어 있을 때까지 배에서 식민지 주민 한 명을 얻습니다. 그런 다음 플레이어는 건물과 농장에 식민자를 설정해야 합니다.
생산자: 상품이 생산됩니다. 특권 : 생산자는 농작물을 1개 더 받습니다. 행동: 모든 플레이어들은 저장소에서 농작물을 받습니다.
상인: 상품을 거래처에 판매합니다. 특권: 상인은 무역상점에서 1금화를 추가로 얻습니다. 행동 : 모든 플레이어들은 농작물을 단 1개만 판매할 수 있습니다.
개척자 : 플랜테이션 정착. 특권 : 정착민은 농장 대신 채석장을 얻을 수 있습니다. 행동: 사용 가능한 농장 중에서 선택한 농장을 얻습니다.
건축가 : 건물을 사고 건축합니다. 특전 : 건축가는 정가보다 1금화 저렴하게 건물을 지을 수 있습니다. 행동: 사용 가능한 건물 중에서 선택하십시오.
선장 : 구세계로 물품을 배송하여 승점을 얻습니다. 특전: 선장은 물품을 선적하면 승점 1점을 추가로 얻습니다. 조치: 화물선에 적재할 상품 유형을 선택하십시오. 배에 실린 이러한 유형의 상품 배럴당 승점 1점을 얻습니다.
광부: 골드러시는 돈을 가져온다! 특권: 광부는 은행에서 1금화를 얻습니다. 조치: 없음.
또한 점령된 보라색 건물에는 역할 행동에 대한 수정 효과가 있습니다.
게임 종료는 다음 이벤트 중 하나가 발생하는 라운드가 끝날 때 발생합니다.
시장 단계가 끝나고 저장소에 남은 이주민이 없을 때
선장 과정에서 승점이 모두 소진되었을 때
한 플레이어가 자신의 건축 필드 12칸에 건물을 모두 지었을 때
온라인 플레이
역할 선택: 게임 보드 오른쪽에 있는 목록에서 원하는 역할을 클릭합니다.
시장 역할: 공급에서 추가 식민지를 얻는 것을 수락하거나 거부합니다. 식민지 개척자는 플레이어에 의해 자동으로 모집됩니다. 건물이나 농장을 클릭하여 식민지 주민을 설정하십시오. 식민지 주민을 클릭하여 San Juan으로 다시 보내십시오(San Juan의 식민지 주민 카운터는 페이지 오른쪽의 플레이어 패널에 있습니다).
생산자 역할 : 상품 생산이 자동화됩니다(소유 상품 카운터는 페이지 오른쪽의 플레이어 패널에 있습니다). 그런 다음, 당신의 특권으로 생산할 수 있는 한 가지 추가 재화를 선택하십시오.
상인 역할: 플레이어 패널에서 적절한 카운터를 클릭하여 판매하려는 상품을 선택합니다.
개척자 역할 : 원하는 농장(또는 채석장)을 클릭합니다. 보드에 배치가 자동화됩니다.
건축가 역할 : 구매하려는 건물을 클릭합니다. 보드에 배치가 자동화됩니다.
선장 역할: 일부 상품을 선적하려는 화물선을 클릭합니다. 그런 다음 플레이어 패널에서 적절한 카운터를 클릭하여 배송하려는 상품 유형을 선택합니다. 선장 단계가 끝나면 보관할 물품(창고 또는 윈드로즈)이 있는 경우 해당 카운터를 클릭합니다. 저장된 상품은 빨간색 프레임으로 강조 표시됩니다.
광부 역할 : 즉시 금화를 얻습니다.
툴팁은 마우스로 게임 요소를 가리켜 역할과 건물에 대한 정보를 제공하는 데 사용할 수 있습니다.
'균형잡힌 게임' 변형
이 변형은 푸에르토리코(보드 게임) Wikipedia 페이지에 나열된 대로 각 플레이어에게 동일한 승리 기회를 제공하는 두 가지 게임 밸런스 수정을 구현합니다.
공장과 대학 건물의 가격이 교환되어 공장 비용은 8금화, 대학 비용은 7금화입니다.
옥수수 농장으로 시작하는 플레이어는 인디고 농장으로 시작하는 플레이어보다 1금화 적게 가지고 시작합니다.
== Two players variant ==
Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts.
This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules.
This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek].
'''Have a good game !'''
60bdcc9f0c896511b3673bd889426bcf7ff809a7
Gamehelpcarcassonne
0
192
1259
2021-08-12T23:34:22Z
Ananstarsha
7468
새 문서: 내용물 1 게임 플레이 2 득점 3 확장 3.1 강 3.2 여관과 대성당 3.3 거래자와 건설업자 3.4 공주와 용 3.5 전략적 변형 게임 플레이...
wikitext
text/x-wiki
내용물
1 게임 플레이
2 득점
3 확장
3.1 강
3.2 여관과 대성당
3.3 거래자와 건설업자
3.4 공주와 용
3.5 전략적 변형
게임 플레이
게임 보드는 게임이 진행되면서 플레이어가 만든 중세 풍경입니다. 게임은 플레이어가 뽑을 수 있도록 하나의 지형 타일을 앞면이 위로 향하게 하고 나머지 71개는 뒷면을 섞은 상태로 시작합니다. 매 턴마다 플레이어는 새로운 지형 타일을 그려서 이미 앞면이 보이도록 타일 옆에 놓습니다. 새 타일은 닿는 타일의 기능을 확장하는 방식으로 배치되어야 합니다. 도로는 도로, 들판은 들판, 도시는 도시로 연결되어야 합니다.
각각의 새 타일을 배치한 후 배치하는 플레이어는 새로 배치된 타일의 기능에 조각("추종자" 또는 "미플"이라고 함)을 배치할 수 있습니다. 배치하는 플레이어는 다른 플레이어가 이미 주장한 기능을 확장하거나 연결하는 타일의 기능을 주장하기 위해 팔로워를 사용할 수 없습니다. 그러나, 상대 플레이어가 주장하는 지형 특징은 그들을 연결하는 타일의 후속 배치에 의해 "공유"될 수 있습니다. 예를 들어, 각각 추종자가 있는 두 개의 필드 타일은 다른 지형 타일에 의해 각 추종자의 플레이어가 공유하는 단일 필드로 연결될 수 있습니다. 공유 기능이 동일한 플레이어 중 한 명이 주장한 동일한 유형의 또 다른 기능에 연결되면 해당 기능에 더 많은 추종자가 있는 해당 플레이어가 해당 기능에 대한 완전한 소유권을 얻습니다.
필드 이외의 지형지물이 완성되면 완성된 지형지물의 모든 미플은 배치한 플레이어에게 반환되어 재사용이 가능합니다. 기능 점수에서 미플이 가장 많은 플레이어가 즉시 점수를 얻습니다(아래 참조).
마지막 타일이 놓이면 게임이 종료됩니다. 이때 모든 기능(필드 포함)은 팔로워가 가장 많은 플레이어에게 점수를 줍니다. 가장 많은 점수를 얻은 플레이어가 게임에서 승리합니다.
득점
플레이어의 턴 동안 도시, 회랑, 도로(필드는 제외)는 완료되었을 때 점수가 매겨집니다. 8개의 타일. 게임이 끝날 때 남은 타일이 없으면 모든 불완전한 기능이 점수가 매겨집니다. 포인트는 기능에서 가장 많은 팔로워를 가진 플레이어에게 수여됩니다.
특정 기능에서 가장 많은 팔로워가 동점인 경우 동점인 모든 플레이어에게 전체 점수가 부여됩니다. 일반적으로(표 참조) 기능에 포함된 타일 수에 따라 점수가 부여됩니다. 이웃 타일에 대한 회랑 점수; 그리고 필드는 연결된 완료된 도시의 수를 기반으로 점수를 매깁니다.
기능에 점수가 매겨지면 해당 기능의 모든 팔로어가 소유자에게 반환됩니다.
특징 플레이 중 완료 게임종료
도시 타일당 2점 + 페넌트당 2점 타일당 1점 + 페넌트당 1점
도로 타일당 1포인트 타일당 1포인트
회랑 주변 타일당 1포인트 + 1포인트 주변 타일당 1포인트 + 1포인트
필드 포인트 없음 필드에 접해 있는 완성된 각 도시에 대해 3점.
수도원 수도원을 둘러싼 타일당 1포인트. 미플을 되돌리려면 완전히 포위되어야 합니다.
확장
강
이 확장은 시작 타일을 대체하는 강을 특징으로 합니다. 강은 발원지에서 호수로 시작하여 같은 방향으로 두 번 돌 수 없습니다.
여관과 대성당
이 확장에는 여관(도로 옆)과 대성당(도시 옆)이 있습니다. 또한 각 색상의 큰 미플이 등장합니다.
여관: 도로가 하나 이상의 여관으로 완성된 경우 각 타일은 1점이 아닌 2점을 얻습니다. 그러나 끝에 여관이 있는 미완성 도로는 점수를 얻지 못합니다.
대성당: 도시가 하나 이상의 대성당으로 완성된 경우. 각 타일과 무기 비용은 2점 대신 3점을 얻습니다. 그러나 대성당이 있는 불완전한 도시는 점수를 얻지 못합니다.
대형 미플: 대형 미플은 1이 아닌 2미플의 가치가 있습니다.
트레이더 및 빌더
이 확장에는 상품 토큰, 건축업자 및 돼지가 있습니다.
상품 토큰: 상품으로 도시를 완성한 사람은 도시에서 상품을 수집합니다. 상품은 포도주(9), 곡식(6), 천(5)입니다. 게임이 끝나면 가장 많은 상품 토큰을 가진 플레이어가 10점을 얻습니다. 여러 플레이어가 동점인 경우 모두 전체 점수를 얻습니다.
빌더: 각 플레이어는 빌더가 있습니다. 적어도 하나의 미플이 있는 도로나 도시에 설치할 수 있습니다. 빌더와 함께 기능을 계속하면 이중 회전을 얻습니다.
돼지: 각 플레이어는 돼지를 가지고 있습니다. 농부와 함께 필드에 놓을 수 있습니다. 돼지는 필드에서 완성된 각 도시에 대해 1점을 얻습니다.
공주와 용
이 확장에는 드래곤, 요정, 마법 포털이 있습니다.
화산: 용이 나타납니다. 드래곤이 나타난 후 드래곤 타일을 놓을 수 있습니다. 화산 타일에는 미플을 놓을 수 없습니다.
드래곤 타일: 각 플레이어는 드래곤이 6칸 이동하거나 움직일 수 없을 때까지 차례로 드래곤을 이동합니다. 방문하는 공간의 모든 수치는 점수를 매기지 않고 소유자에게 반환됩니다.
공주: 미플을 배치하는 대신 도시에 있는 미플을 주인에게 되돌릴 수 있습니다.
마법 포털: 이전에 배치한 타일 대신 이전에 배치한 타일에 미플을 배치할 수 있습니다.
요정: 그것은 누구의 것도 아니다. 배치 대신 미플 중 하나에 할당할 수 있습니다. 당신의 차례가 시작될 때 여전히 당신 옆에 있다면, 당신은 1점을 얻습니다. 그 위에 있는 모든 인물은 용으로부터 보호됩니다. 요정이 당신의 미플 중 하나 옆에 있다면 어떤 기능이든 득점하면 3점을 얻습니다.
전략적 변형
각 플레이어는 시작 시 3개의 타일을 가지고 있습니다. 각 턴에 타일이 그려지고 플레이어의 손에 추가됩니다. 그들은 매번 배치할 것을 선택합니다.
1dc61ec2235cf5d934b8e7c58d9b052809a7690e
1264
1259
2021-08-13T00:45:56Z
Ananstarsha
7468
wikitext
text/x-wiki
내용물
1 게임 플레이
2 득점
3 확장
3.1 강
3.2 여관과 대성당
3.3 거래자와 건설업자
3.4 공주와 용
3.5 전략적 변형
게임 플레이
게임 보드는 게임이 진행되면서 플레이어가 만든 중세 풍경입니다. 게임은 플레이어가 뽑을 수 있도록 하나의 지형 타일을 앞면이 위로 향하게 하고 나머지 71개는 뒷면을 섞은 상태로 시작합니다. 매 턴마다 플레이어는 새로운 지형 타일을 그려서 이미 앞면이 보이도록 타일 옆에 놓습니다. 새 타일은 닿는 타일의 기능을 확장하는 방식으로 배치되어야 합니다. 도로는 도로, 들판은 들판, 도시는 도시로 연결되어야 합니다.
각각의 새 타일을 배치한 후 배치하는 플레이어는 새로 배치된 타일의 기능에 조각("추종자" 또는 "미플"이라고 함)을 배치할 수 있습니다. 배치하는 플레이어는 다른 플레이어가 이미 주장한 기능을 확장하거나 연결하는 타일의 기능을 주장하기 위해 팔로워를 사용할 수 없습니다. 그러나, 상대 플레이어가 주장하는 지형 특징은 그들을 연결하는 타일의 후속 배치에 의해 "공유"될 수 있습니다. 예를 들어, 각각 추종자가 있는 두 개의 필드 타일은 다른 지형 타일에 의해 각 추종자의 플레이어가 공유하는 단일 필드로 연결될 수 있습니다. 공유 기능이 동일한 플레이어 중 한 명이 주장한 동일한 유형의 또 다른 기능에 연결되면 해당 기능에 더 많은 추종자가 있는 해당 플레이어가 해당 기능에 대한 완전한 소유권을 얻습니다.
필드 이외의 지형지물이 완성되면 완성된 지형지물의 모든 미플은 배치한 플레이어에게 반환되어 재사용이 가능합니다. 기능 점수에서 미플이 가장 많은 플레이어가 즉시 점수를 얻습니다(아래 참조).
마지막 타일이 놓이면 게임이 종료됩니다. 이때 모든 기능(필드 포함)은 팔로워가 가장 많은 플레이어에게 점수를 줍니다. 가장 많은 점수를 얻은 플레이어가 게임에서 승리합니다.
득점
플레이어의 턴 동안 성, 수도원, 길(필드는 제외)는 완료되었을 때 점수가 매겨집니다. 8개의 타일. 게임이 끝날 때 남은 타일이 없으면 모든 불완전한 기능이 점수가 매겨집니다. 포인트는 기능에서 가장 많은 팔로워를 가진 플레이어에게 수여됩니다.
특정 기능에서 가장 많은 팔로워가 동점인 경우 동점인 모든 플레이어에게 전체 점수가 부여됩니다. 일반적으로(표 참조) 기능에 포함된 타일 수에 따라 점수가 부여됩니다. 이웃 타일에 대한 회랑 점수; 그리고 필드는 연결된 완료된 도시의 수를 기반으로 점수를 매깁니다.
기능에 점수가 매겨지면 해당 기능의 모든 팔로어가 소유자에게 반환됩니다.
점수 계산 게임 도중 길,성,수도원등을 완성했을 때 게임 끝날 때까지 완성하지 못했을 때
성 지형 타일당 2점 + 방패문양 한 개마다 2점 지형 타일당 1점 + 방패문양 한 개마다 1점
길 지형 타일당 1점 지형 타일당 1점
농장 포인트 없음 농장과 접해있거나 농장 안에 있는 완성된 성하나 마다 3점
수도원 9점 수도원을 둘러싼 타일당 1포인트. 미플을 되돌리려면 완전히 포위되어야 합니다.
확장
강
이 확장은 시작 타일을 대체하는 강을 특징으로 합니다. 강은 발원지에서 호수로 시작하여 같은 방향으로 두 번 돌 수 없습니다.
여관과 대성당
이 확장에는 여관(도로 옆)과 대성당(도시 옆)이 있습니다. 또한 각 색상의 큰 미플이 등장합니다.
여관: 도로가 하나 이상의 여관으로 완성된 경우 각 타일은 1점이 아닌 2점을 얻습니다. 그러나 끝에 여관이 있는 미완성 도로는 점수를 얻지 못합니다.
대성당: 도시가 하나 이상의 대성당으로 완성된 경우. 각 타일과 무기 비용은 2점 대신 3점을 얻습니다. 그러나 대성당이 있는 불완전한 도시는 점수를 얻지 못합니다.
대형 미플: 대형 미플은 1이 아닌 2미플의 가치가 있습니다.
트레이더 및 빌더
이 확장에는 상품 토큰, 건축업자 및 돼지가 있습니다.
상품 토큰: 상품으로 도시를 완성한 사람은 도시에서 상품을 수집합니다. 상품은 포도주(9), 곡식(6), 천(5)입니다. 게임이 끝나면 가장 많은 상품 토큰을 가진 플레이어가 10점을 얻습니다. 여러 플레이어가 동점인 경우 모두 전체 점수를 얻습니다.
빌더: 각 플레이어는 빌더가 있습니다. 적어도 하나의 미플이 있는 도로나 도시에 설치할 수 있습니다. 빌더와 함께 기능을 계속하면 이중 회전을 얻습니다.
돼지: 각 플레이어는 돼지를 가지고 있습니다. 농부와 함께 필드에 놓을 수 있습니다. 돼지는 필드에서 완성된 각 도시에 대해 1점을 얻습니다.
공주와 용
이 확장에는 드래곤, 요정, 마법 포털이 있습니다.
화산: 용이 나타납니다. 드래곤이 나타난 후 드래곤 타일을 놓을 수 있습니다. 화산 타일에는 미플을 놓을 수 없습니다.
드래곤 타일: 각 플레이어는 드래곤이 6칸 이동하거나 움직일 수 없을 때까지 차례로 드래곤을 이동합니다. 방문하는 공간의 모든 수치는 점수를 매기지 않고 소유자에게 반환됩니다.
공주: 미플을 배치하는 대신 도시에 있는 미플을 주인에게 되돌릴 수 있습니다.
마법 포털: 이전에 배치한 타일 대신 이전에 배치한 타일에 미플을 배치할 수 있습니다.
요정: 그것은 누구의 것도 아니다. 배치 대신 미플 중 하나에 할당할 수 있습니다. 당신의 차례가 시작될 때 여전히 당신 옆에 있다면, 당신은 1점을 얻습니다. 그 위에 있는 모든 인물은 용으로부터 보호됩니다. 요정이 당신의 미플 중 하나 옆에 있다면 어떤 기능이든 득점하면 3점을 얻습니다.
전략적 변형
각 플레이어는 시작 시 3개의 타일을 가지고 있습니다. 각 턴에 타일이 그려지고 플레이어의 손에 추가됩니다. 그들은 매번 배치할 것을 선택합니다.
58a7ec49ac351c8eb9de88d85320da5d6ebfc7e1
Gamehelpsaboteur
0
32
1260
1025
2021-08-13T00:10:46Z
Ananstarsha
7468
/* Goal */
wikitext
text/x-wiki
목표
▷ 게임 목표 : 만약 광부들이 금덩이를 캐내는데 성공한다면 광부들은 보상으로 금덩이를 받고, 방해꾼들은 빈손인채로 쫓겨 납니다.
하지만 그러지 못한다면 방해꾼들이 금덩이를 가로챕니다.
3라운드가 끝난 뒤, 금덩이를 가장 많이 모은 사람이 승리합니다.
== Rules summary ==
On your turn, you must click on a card from your hand to select it, then play this card or discard it.
You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card.
The cards are of several types:
* 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card.
* 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score).
* 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you.
* 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about.
* 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove.
== Cards in play ==
* 44 'Path' cards
* 9 'Sabotage' cards (three for each tool)
* 6 'Repair a tool' cards (two for each tool)
* 3 'Repair a tool among these two' cards (one for each combination of two tools)
* 5 'Map' cards (one less than in the box set, as requested by the game author)
* 3 'Rock fall' cards
* 28 'Gold' cards
** 16 with one gold nugget
** 8 with two gold nuggets
** 4 with three gold nuggets
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
The Official Anthem of Saboteur designed by '''Dzikidon''' and '''Sikora8a'''
Music - '''Adele - Skyfall''':
*This is the end
*Hold your breath and count to ten
*Feel the Earth move and then
*Hear your axe burst again
*For this is the end
*I’ve digged and dreamt this moment
*I will repair I owe them
*Even tho' I’m broken
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*At rock fall
*At rock fall
*Rock fall is where we start
*A thousand miles and cards apart
*Where roads collide and caves are dark
*You may fix my trolley
*You can break my lamp
*But you’ll never have my gold
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*(Let the rock fall)
*When it crumbles
*We will stand tall) / x2
*Where you go I go
*What you see I see
*I know I'd never be me
*Without the security
*Of your fixing cards
*Keeping me from harm
*Put your end in their straight
*And we'll stand
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*Let the rock fall
*We will stand tall
*At rock faaall
e4fadcfbe13dc68b138f00233d55acf19a753a63
1261
1260
2021-08-13T00:11:24Z
Ananstarsha
7468
/* Rules summary */
wikitext
text/x-wiki
목표
▷ 게임 목표 : 만약 광부들이 금덩이를 캐내는데 성공한다면 광부들은 보상으로 금덩이를 받고, 방해꾼들은 빈손인채로 쫓겨 납니다.
하지만 그러지 못한다면 방해꾼들이 금덩이를 가로챕니다.
3라운드가 끝난 뒤, 금덩이를 가장 많이 모은 사람이 승리합니다.
▷ 게임 방법
게임 진행은 크게 2단계로 구분됩니다.
1. 행동하기
1) 길 카드 1장을 사용하여 동굴 미로에 배치
2) 행동카드 1장을 사용하기
3) 아무 카드 1장을 뒷면이 보이게 버리기
자신의 차례에 손에서 카드를 클릭하여 선택한 다음 이 카드를 사용하거나 버려야 합니다. 카드 위에 나타나는 '회전' 화살표를 클릭하여 '경로' 카드를 재생하기 전에 회전할 수도 있습니다.
카드에는 여러 유형이 있습니다.
'경로' 카드: 이미 있는 카드와 호환되는 경우 이 카드를 사용하여 미로를 확장할 수 있습니다. 이렇게 하려면 카드를 넣을 위치를 클릭합니다.
'사보타지' 카드: 표시된 유형의 다른 플레이어의 도구를 부술 수 있습니다. 이렇게 하려면 대상 플레이어의 패널(점수 아래)에서 해당 도구를 클릭합니다.
'수리' 카드: 표시된 유형의 귀하 또는 다른 플레이어의 파손된 도구를 수리할 수 있습니다. 이렇게 하려면 대상 플레이어의 패널(점수 아래)에서 해당 도구를 클릭하거나 앞에 있는 '사보타주' 카드를 클릭합니다.
'지도' 카드: 이 카드를 모든 '엔드' 카드에서 사용하여 보물이 거기에 있는지 여부를 확인할 수 있습니다(당신만 정보를 얻을 수 있고 다른 플레이어는 아무것도 볼 수 없습니다). 모든 것을 알고 싶은 '종료' 카드를 클릭하기만 하면 됩니다.
'낙석' 카드: 이 카드를 사용하면 미로의 '경로' 카드를 제거할 수 있습니다. 제거하려는 카드를 클릭하기만 하면 됩니다.
== Cards in play ==
* 44 'Path' cards
* 9 'Sabotage' cards (three for each tool)
* 6 'Repair a tool' cards (two for each tool)
* 3 'Repair a tool among these two' cards (one for each combination of two tools)
* 5 'Map' cards (one less than in the box set, as requested by the game author)
* 3 'Rock fall' cards
* 28 'Gold' cards
** 16 with one gold nugget
** 8 with two gold nuggets
** 4 with three gold nuggets
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
The Official Anthem of Saboteur designed by '''Dzikidon''' and '''Sikora8a'''
Music - '''Adele - Skyfall''':
*This is the end
*Hold your breath and count to ten
*Feel the Earth move and then
*Hear your axe burst again
*For this is the end
*I’ve digged and dreamt this moment
*I will repair I owe them
*Even tho' I’m broken
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*At rock fall
*At rock fall
*Rock fall is where we start
*A thousand miles and cards apart
*Where roads collide and caves are dark
*You may fix my trolley
*You can break my lamp
*But you’ll never have my gold
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*(Let the rock fall)
*When it crumbles
*We will stand tall) / x2
*Where you go I go
*What you see I see
*I know I'd never be me
*Without the security
*Of your fixing cards
*Keeping me from harm
*Put your end in their straight
*And we'll stand
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*Let the rock fall
*We will stand tall
*At rock faaall
f8daf8d6984592b6abcc326b8dc2476c8325acdd
1262
1261
2021-08-13T00:11:43Z
Ananstarsha
7468
/* Cards in play */
wikitext
text/x-wiki
목표
▷ 게임 목표 : 만약 광부들이 금덩이를 캐내는데 성공한다면 광부들은 보상으로 금덩이를 받고, 방해꾼들은 빈손인채로 쫓겨 납니다.
하지만 그러지 못한다면 방해꾼들이 금덩이를 가로챕니다.
3라운드가 끝난 뒤, 금덩이를 가장 많이 모은 사람이 승리합니다.
▷ 게임 방법
게임 진행은 크게 2단계로 구분됩니다.
1. 행동하기
1) 길 카드 1장을 사용하여 동굴 미로에 배치
2) 행동카드 1장을 사용하기
3) 아무 카드 1장을 뒷면이 보이게 버리기
자신의 차례에 손에서 카드를 클릭하여 선택한 다음 이 카드를 사용하거나 버려야 합니다. 카드 위에 나타나는 '회전' 화살표를 클릭하여 '경로' 카드를 재생하기 전에 회전할 수도 있습니다.
카드에는 여러 유형이 있습니다.
'경로' 카드: 이미 있는 카드와 호환되는 경우 이 카드를 사용하여 미로를 확장할 수 있습니다. 이렇게 하려면 카드를 넣을 위치를 클릭합니다.
'사보타지' 카드: 표시된 유형의 다른 플레이어의 도구를 부술 수 있습니다. 이렇게 하려면 대상 플레이어의 패널(점수 아래)에서 해당 도구를 클릭합니다.
'수리' 카드: 표시된 유형의 귀하 또는 다른 플레이어의 파손된 도구를 수리할 수 있습니다. 이렇게 하려면 대상 플레이어의 패널(점수 아래)에서 해당 도구를 클릭하거나 앞에 있는 '사보타주' 카드를 클릭합니다.
'지도' 카드: 이 카드를 모든 '엔드' 카드에서 사용하여 보물이 거기에 있는지 여부를 확인할 수 있습니다(당신만 정보를 얻을 수 있고 다른 플레이어는 아무것도 볼 수 없습니다). 모든 것을 알고 싶은 '종료' 카드를 클릭하기만 하면 됩니다.
'낙석' 카드: 이 카드를 사용하면 미로의 '경로' 카드를 제거할 수 있습니다. 제거하려는 카드를 클릭하기만 하면 됩니다.
플레이 중인 카드
44 굴 카드(출발지카드1장 + 목적지카드 3장 + 길카드 40장)
27 행동카드
28 금덩이카드
== Roles ==
Roles are randomly selected among a set that depends upon the number of players:
* with 3 players: 1 saboteur and 3 gold diggers
* with 4 players: 1 saboteur and 4 gold diggers
* with 5 players: 2 saboteurs and 4 gold diggers
* with 6 players: 2 saboteurs and 5 gold diggers
* with 7 players: 3 saboteurs and 5 gold diggers
* with 8 players: 3 saboteurs and 6 gold diggers
* with 9 players: 3 saboteurs and 7 gold diggers
* with 10 players: 4 saboteurs and 7 gold diggers
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
The Official Anthem of Saboteur designed by '''Dzikidon''' and '''Sikora8a'''
Music - '''Adele - Skyfall''':
*This is the end
*Hold your breath and count to ten
*Feel the Earth move and then
*Hear your axe burst again
*For this is the end
*I’ve digged and dreamt this moment
*I will repair I owe them
*Even tho' I’m broken
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*At rock fall
*At rock fall
*Rock fall is where we start
*A thousand miles and cards apart
*Where roads collide and caves are dark
*You may fix my trolley
*You can break my lamp
*But you’ll never have my gold
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*(Let the rock fall)
*When it crumbles
*We will stand tall) / x2
*Where you go I go
*What you see I see
*I know I'd never be me
*Without the security
*Of your fixing cards
*Keeping me from harm
*Put your end in their straight
*And we'll stand
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*Let the rock fall
*We will stand tall
*At rock faaall
42e9aba0c764a4a3606e9d1698f1c6509f9c79ce
1263
1262
2021-08-13T00:12:00Z
Ananstarsha
7468
/* Roles */
wikitext
text/x-wiki
목표
▷ 게임 목표 : 만약 광부들이 금덩이를 캐내는데 성공한다면 광부들은 보상으로 금덩이를 받고, 방해꾼들은 빈손인채로 쫓겨 납니다.
하지만 그러지 못한다면 방해꾼들이 금덩이를 가로챕니다.
3라운드가 끝난 뒤, 금덩이를 가장 많이 모은 사람이 승리합니다.
▷ 게임 방법
게임 진행은 크게 2단계로 구분됩니다.
1. 행동하기
1) 길 카드 1장을 사용하여 동굴 미로에 배치
2) 행동카드 1장을 사용하기
3) 아무 카드 1장을 뒷면이 보이게 버리기
자신의 차례에 손에서 카드를 클릭하여 선택한 다음 이 카드를 사용하거나 버려야 합니다. 카드 위에 나타나는 '회전' 화살표를 클릭하여 '경로' 카드를 재생하기 전에 회전할 수도 있습니다.
카드에는 여러 유형이 있습니다.
'경로' 카드: 이미 있는 카드와 호환되는 경우 이 카드를 사용하여 미로를 확장할 수 있습니다. 이렇게 하려면 카드를 넣을 위치를 클릭합니다.
'사보타지' 카드: 표시된 유형의 다른 플레이어의 도구를 부술 수 있습니다. 이렇게 하려면 대상 플레이어의 패널(점수 아래)에서 해당 도구를 클릭합니다.
'수리' 카드: 표시된 유형의 귀하 또는 다른 플레이어의 파손된 도구를 수리할 수 있습니다. 이렇게 하려면 대상 플레이어의 패널(점수 아래)에서 해당 도구를 클릭하거나 앞에 있는 '사보타주' 카드를 클릭합니다.
'지도' 카드: 이 카드를 모든 '엔드' 카드에서 사용하여 보물이 거기에 있는지 여부를 확인할 수 있습니다(당신만 정보를 얻을 수 있고 다른 플레이어는 아무것도 볼 수 없습니다). 모든 것을 알고 싶은 '종료' 카드를 클릭하기만 하면 됩니다.
'낙석' 카드: 이 카드를 사용하면 미로의 '경로' 카드를 제거할 수 있습니다. 제거하려는 카드를 클릭하기만 하면 됩니다.
플레이 중인 카드
44 굴 카드(출발지카드1장 + 목적지카드 3장 + 길카드 40장)
27 행동카드
28 금덩이카드
▶ 플레이어 역할 뽑기
플레이어 수에 따라서 게임에 사용하는 광부/방해꾼 카드의 수가 달라집니다. 사용하지 않는 광부/방해꾼 카드는 게임 상자에 다시 넣어두세요.
- 3명 : 광부 3장 + 방해꾼 1장
- 4명 : 광부 4장 + 방해꾼 1장
- 5명 : 광부 4장 + 방해꾼 2장
- 6명 : 광부 5장 + 방해꾼 2장
- 7명 : 광부 5장 + 방해꾼 3장
- 8명 : 광부 6장 + 방해꾼 3장
- 9명 : 광부 7장 + 방해꾼 3장
- 10명 : 모든 광부/방해꾼 카드 사용
== Available variants ==
The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum!
Two variants are about gold sharing:
* '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed!
* '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!)
Two variants are about gameplay:
* '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose!
* '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded)
'''Have a good game !'''
The Official Anthem of Saboteur designed by '''Dzikidon''' and '''Sikora8a'''
Music - '''Adele - Skyfall''':
*This is the end
*Hold your breath and count to ten
*Feel the Earth move and then
*Hear your axe burst again
*For this is the end
*I’ve digged and dreamt this moment
*I will repair I owe them
*Even tho' I’m broken
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*Let the rock fall
*When it crumbles
*We will stand tall
*Face it all together
*At rock fall
*At rock fall
*Rock fall is where we start
*A thousand miles and cards apart
*Where roads collide and caves are dark
*You may fix my trolley
*You can break my lamp
*But you’ll never have my gold
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*(Let the rock fall)
*When it crumbles
*We will stand tall) / x2
*Where you go I go
*What you see I see
*I know I'd never be me
*Without the security
*Of your fixing cards
*Keeping me from harm
*Put your end in their straight
*And we'll stand
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*Let the rock fall (Let the rock fall)
*When it crumbles (When it crumbles)
*We will stand tall (We will stand tall)
*Face it all together
*At rock fall
*Let the rock fall
*We will stand tall
*At rock faaall
aef9dd47d7428ee3dd7db10aa750c9d583317817
Gamehelpdarkagent
0
193
1267
2021-08-13T18:15:12Z
Ananstarsha
7468
새 문서: 내용물 1 Dark Agent 1.1 목표: 1.2 기본 게임 개념: 1.3 팀을 선택하십시오. 1.4 1단계: 위성 단계 1.5 2단계: 에이전트 단계 1.6 게임 종료: 1.7...
wikitext
text/x-wiki
내용물
1 Dark Agent
1.1 목표:
1.2 기본 게임 개념:
1.3 팀을 선택하십시오.
1.4 1단계: 위성 단계
1.5 2단계: 에이전트 단계
1.6 게임 종료:
1.7 위성 이동:
1.8 위성 효과:
1.9 타겟팅:
1.10 스파이 기어:
1.11 조치:
1.12 목표:
1.13 사용자:
1.14 싱글 플레이어:
1.15 전력:
2 국가 – 정보 기관 – 기관 전력 – 설명
2.1 '''오리지날 엔트리'''
2.2 게임에 대한 설명:
다크 에이전트
이 게임이 꽤 흥미롭긴 하지만 지시사항은 아주 아주 명확하지 않았어요 다음 지침 집합은 원본 프랑스어 규칙, 재생을 통한 테스트 및 이 Wiki의 맨 아래에 있는 원본 지침을 기반으로 합니다.
그 게임은 미디어 넥타이가 이상하고 "미디어"라는 단어를 꽤 많이 사용한다. 기본적으로는 계속하라는 뜻인데, 게임 속 영어 번역은 거르는 게 아니라 그냥 건너뛴다. 미디어 타일이라는 타일이 있어서 3명의 위치를 바꿀 수 있지만 그건 또 다른 것이다.
또한, 이 한 명의 플레이어를 플레이할 계획이라면 하단의 참고 사항을 읽으십시오. 몇 가지 알아야 할 사항이 있습니다. 당신이 이기기 위해 노력한다면 규칙은 아주 다릅니다.
목표:
다크 에이전트의 목표는 "포섭 목표" 임무와 암살 임무에 비밀 요원들을 보내는 방법으로 가장 많은 승리 포인트를 얻는 것입니다.
기본 게임 개념:
보드는 7개의 열과 6개의 행으로 구성되어 있습니다. 맨 위 행은 열당 최대 3개의 위성을 수용할 수 있는 위성 행입니다. 아래쪽 6개 행은 에이전트 타일(에이전트, 스파이 장비, 가드, 라 팜 니키타 등)로 채워집니다.
게임은 10라운드로 진행됩니다. 각 라운드에는 보드의 특정 부분에서 수행되는 2개의 단계가 있습니다.
팀을 선택하십시오.
제일 먼저 할 일은 당신이 원하는 첩보기관을 고르는 것입니다. 그들은 모두 다른 능력을 가지고 있습니다. 좋은 걸로 골라요.
1단계: 위성 단계
게임의 첫 부분은 위성을 이동할 수 있게 해줍니다. 열의 위성 수를 통해 범위(에이전트 행 아래까지 볼 수 있는 범위)를 알 수 있기 때문에 이 작업이 수행됩니다. 3개의 위성을 서로 다른 열에 배치할 수 있으며 특수 타일 또는 전원을 사용하지 않는 한 에이전트 보드의 타일에서는 위성으로 볼 수 없는 작업을 수행할 수 없습니다. 따라서 일반적으로 위성이 있는 열 내에서만 작동할 수 있습니다.
2단계: 에이전트 단계
위성 단계를 마치면 요원 보드로 이동하여 임무를 수행하고, 비밀 무기를 입수하고, 요원을 배치하고, 사람들을 죽일 수 있습니다. 재미있는 일을 할 수 있습니다.
수정자를 사용하지 않고 각 위성이 볼 수 있는 하나의 타일/공간을 열 및 범위를 고려하여 활성화할 수 있습니다.
각 위성에 대해 조치를 취하거나 차례를 통과하면 됩니다. 암살 시도나 포획 이벤트에 실패해도 차례가 종료됩니다.
게임 종료:
모든 목표가 포착되거나 시간이 부족하면 게임이 종료됩니다. 승자는 획득한 승점 수와 현재 에이전트 보드에 있는 에이전트의 가치에 따라 결정됩니다.
위성 이동:
첫 번째 턴을 시작할 때 위성 3개를 맨 위 행의 열로 열린 공간에 배치합니다. 위성 열의 각 섹션은 최소 숫자 없이 최대 3개의 위성을 수용할 수 있습니다.
다음 순서에 따라 두 가지 중 하나를 수행할 수 있습니다.
옵션 1: 한 위성을 다른 색상의 위성과 교환
옵션 2: 두 위성을 해당 열에서 다른 열의 빈 공간으로 이동합니다.
위성 효과:
위성은 어떤 타일/공간과 상호 작용할 수 있는지 나타냅니다. 위성 구성에 따라 1, 2, 3 또는 5개 행이 아래로 표시됩니다.
한 열의 총 위성 수는 표적이 될 수 있는 아래쪽 공간을 나타냅니다.
위성 중 하나에만 해당 - 첫 번째 열을 대상으로 할 수 있습니다.
위성 중 하나 + 다른 위성 하나 – 처음 2개 열을 대상으로 할 수 있습니다.
위성 중 하나 + 다른 두 위성 – 처음 3개 열을 대상으로 할 수 있습니다.
3개의 위성이 모두 한 열에 있으므로 열의 모든 행을 대상으로 지정할 수 있습니다.
참고* 수퍼 위성 토큰이 있으므로 전체 열을 볼 수 있지만, 여전히 대상이 될 수 있는 다른 위성이 없으면 해당 열에서 작동할 수 없습니다. 업그레이드입니다. 온라인 버전의 게임을 사용하면 위성 보드의 어떤 공간에도 게임을 배치할 수 있습니다. 이렇게 해서는 안 됩니다.
대상:
기본적으로 4가지 종류의 타일이 있습니다. 스파이 장비, 액션, 미션 & 피플
스파이 장비:
스파이 기어는 맨 위 타일이 위를 향하게 쌓아올린 상태에서 시작됩니다. 그런 다음 플레이어가 턴할 때 스파이 보드의 빈 사각형에 배치됩니다. 스파이 보드의 하나가 표적이 될 경우, 차례대로 선택하여 보드로 이동할 수 있습니다. 한 번에 3개씩 드실 수 있습니다. 버리면 안 돼요.
갑옷 – 암살이 실패할 경우 보드에서 에이전트가 제거되는 것을 방지합니다.
로켓 발사기 - 롤링 다이 하나를 원하는 숫자로 변경할 수 있습니다(항상 6이어야 함). 온라인 게임에서는 6으로 자동 변경됨)
균일 – 하위 레벨의 캐릭터가 일반적으로 공격할 수 없는 상위 레벨의 캐릭터를 공격할 수 있습니다. (온라인 게임에서 이것의 일부가 깨진 것 같습니다. 쓸모가 없어 보이는데, 니키타를 레벨 1 스파이로 공격할 때만 필요했어.)
쌍안경 – 선택한 미션 대상에 대해 +5를 롤링합니다.
Jet Pack – 에이전트 중 하나를 배디와 교환합니다(사람뿐만 아니라 다른 능력도 있습니다). 스파이를 활성화하면 다른 남자를 그의 공간으로 교환하고 그의 공간에 있는 스파이를 사용하여 스파이를 타겟으로 삼을 수 있기 때문에 이 또한 이상해진다.)
아드레날린 – 첫 번째 스파이의 공격량을 총 공격에 추가합니다(이 스파이는 온라인 상태가 매우 불안정하며, 러시아를 2발로 사용하면 130개 이상의 공격을 받을 수 있습니다).
스나이퍼 라이플 – 에이전트 보드의 아무 곳이나 사람을 공격합니다.
위성 해킹 – 사용자의 위성이 아닌 추가 위성을 활성화합니다.
공기 주입식 보트 – 스파이를 빈 공간에 배치
폭발물 – 주변에 나쁜 물체가 있을 때 대상을 공격할 수 있습니다.
액션
공급: 기어 스택에서 상단 타일을 제거합니다.
지원: 빈 공간에 스파이를 배치합니다.
미디어: 3개의 타일을 가져다가(미션 제외) 원하는 대로 다시 넣습니다.
언더커버: 이중 에이전트 토큰 복구
목표:
게임에서 승리하는 것 중 일부는 임무를 완수하는 것이다. 모든 미션은 승점 6점입니다.
임무를 완수하려면 스파이나 이중 요원을 활성화한 다음 임무를 "공격"해야 합니다. 미션에 성공하려면 주변에 악당이 있을 수 없으며 방어 번호(방어 번호)보다 높게 굴러가야 합니다. 선택한 에이전트의 기능 수준 또는 쌍안경(노란색 마커)으로 롤을 수정할 수 있습니다.
임무를 완수하는 것 외에도 그들의 특별한 능력을 위해 사용할 수 있습니다.
미션을 완료하면 각 라운드에서 해당 기능을 사용할 수 있으며 플레이어 보드에 상주합니다. 사용하면 일회성이고 다른 플레이어들이 사용할 수 있도록 플레이를 유지합니다.
죄수들: 당신의 부하들 중 하나를 당신의 부하가 아닌 다른 사람과 바꿔라.
스파이들은 실패해도 자리를 뜨지 않는다
빅 스틱: +3 공격
명령 센터: 모든 위성이 슈퍼 위성이 됨(모든 열을 대상으로 할 수 있음)
외교: 보드를 한 단계 위로 이동합니다.
사람:
사람들은 방어와 레벨/승점 두 가지 기본 속성을 가지고 있습니다.
당신의 스파이들:
한 명의 스파이로 시작한다면 이 사람을 절대 잃을 수 없을 거야 (어떤 일에 실패하더라도) 새로운 스파이는 보트 타일이나 지원 조치를 사용하여 보드 위로 이동해야 합니다. 암살에 실패하면 요원은 이사회에서 제외되고 총점에서 요원의 포인트가 차감됩니다. 그를 다시 연주하면 포인트를 되찾을 수 있을 거야. 가장 낮은 레벨에서 가장 높은 레벨로만 플레이할 수 있습니다.
이중 에이전트 토큰:
이 제품은 선택한 배디를 임무나 암살에 사용할 수 있는 소모품입니다. 사용한 후에는 "잠복" 타일을 선택하여 다시 사용할 수 있습니다.
방어:
누군가를 암살하기 위해서는 4개의 주사위를 던져서 상대방의 방어력보다 높은 숫자를 얻어야 합니다. 방어는 방패에 표시되며 숫자 또는 "+" 기호가 있는 숫자일 수 있습니다. 보통 숫자는 바로 그 숫자입니다. 숫자+는 해당 숫자에 6측 다이 롤(def + 1d6)의 값을 더한 값입니다.
사람을 죽이면 트로피 냉동고에 시체를 넣어 승점 만점을 받게 돼 온라인 버전에서는 어떤 이유로 인해 이를 음수로 간주합니다.
참고* 자기보다 높은 수준의 사람을 공격할 수 없는 정비사가 있지만, 온라인 버전에서는 고장날 수 있다고 생각합니다. 유일한 제약은 L1 스파이가 니키타를 공격할 수 없다는 것 같고, 당신이 앞서 말한 유니폼을 사용해야만 한다는 것 같습니다(그러나 어쨌든 그녀는 당신을 망가뜨릴 것이므로 의미가 없습니다).
공격:
살인(임무 완료 중)을 수행하려면 에이전트와 대상을 선택해야 합니다. 각 열에 사용할 모든 타일을 대상으로 할 수 있는 위성이 있어야 합니다. 그러면 화면 상단에 공격 옵션이 있습니다. 4개의 검은 주사위를 굴려 수식어를 추가해 주세요. 여기에는 요원 수준과 장비 또는 임무의 보너스가 포함됩니다.
레벨 2 에이전트가 있는 경우 목표물에 대해 4d6 + 2를 롤링할 수 있습니다. 주사위 4에 최대 24개로 레벨 3(20수비) 가드를 맞출 가능성은 낮습니다. 최대치에 비해 정말 높은 18롤을 굴려야 합니다. 게임 화면 하단에 오즈 테이블이 있습니다.
경비원을 죽이면 승점이 나오고 스파이를 죽이면 부사장이 되고 스파이 장비 더미에서 맨 위 타일을 떼어낼 수 있어
타겟팅 및 이동:
에이전트를 활성화하면 남은 시간 동안 활성 상태이고 현재 위치가 목표입니다. 이건 합법이야.
트래비스가 제트팩을 가지고 있어 스파이와 다른 두 사람을 목표로 하고 있어요 둘 다 죽인 다음 제트기를 이용해 다른 남자와 바꿔치기하죠 스파이는 어디로 가든지 여전히 활개치고 있어요 그가 바꾼 놈이 목표물 광장에 있어서 공격하기 쉽죠
마찬가지로, 외교 옵션을 사용하면 이사회는 이동하지만 대상은 이동하지 않습니다. 그래서 제임스는 스파이를 노리고 다른 놈들에게 그들을 죽이고 새로운 사람들을 노리고 그들을 죽일 수 있습니다. 제트팩과 저격총 두 자루만 있으면 이론적으로 한 번에 6명을 죽일 수 있어
싱글 플레이어:
기능적으로 단일 플레이어는 다중 플레이어와 동일하지만…
1번 목표를 포착해야 한다면 2번 목표: 나쁜 여자 스파이를 죽여야 합니다. 하지만 이 두 가지는 35점을 얻기 전에 할 수 없습니다. 41점 이상(레이디와 미션은 6점이므로 35점이 없으면 차례가 끝날 때 41점으로 끝나지 않는다.) 두 가지 목표를 포착하면 패배한다. 시간이 부족하면 시간을 낭비하게 된다. 레이디와 목표를 얻었지만 마지막에 41점 미만을 획득하면 패배한다.
목표 1개만 달성하고 여자를 죽이고 41점 이상을 획득해야 합니다.
그 두 가지 중 첫 번째가 이루어지면 바로 게임이 끝날 것이다.
파워:
국가 – 정보 기관 – 기관 전력 – 설명
프랑스 – DGSE – MEDIA FRIENDY – MEDIA 카드를 사용해도 턴이 끝나지 않고 목표를 이동할 수 있습니다.
영국 – MI6 – 목표 교환 – 목표 및/또는 전술 카드의 위치를 바꿀 수 있습니다.
독일 – BND – 추가 장비 – 예비 장비에 한 개의 공급 장치를 더 채웁니다.
미국 – CIA – Alliance – 적과 교전할 경우, 보초병은 이중 요원이 될 수 있습니다.
러시아 – SVR – 계층 없음 – 아드레날린 효과는 두 배로 증가합니다.
이스라엘 – 모사드 – 그림자 킬러 – 눈에 띄지 않는 스파이 또는 보초를 공격합니다.
스웨덴 – UNDK – BUTTER AND MONEY – 조준력과 공격력을 사용할 수 있으며, 보너스 ATK는 다른 플레이어에 의해 무력화된 목표에 해당합니다.
중국 – Guong BO – 카피 마스터 – 다른 기관이 획득한 모든 목표의 힘을 복제합니다.
일본 – Naicho – Kamikaze – ATK +2에서 스파이들의 상처.
캐나다 – CSIS – PEACE MASTER – 차례대로 UN 평화 조치를 활성화할 수 있습니다(교대 카드 상승).
이집트 – GIP – REVOLUTION – TDO를 UN 평화 조치의 반대 방향으로 회전시킵니다(교대 카드가 내려감).
바티칸 – 스위스 가드 – 디바인 – 연기 전에 주사위를 굴립니다.
노르웨이 – NIS – 헬리코 마스터 – 각 턴마다 한 번의 무료 지원 조치가 허용되었습니다.
벨기에 – SGRS – J.C. VAN DAME – Jean Claude의 Spirit을 +1 ATK 스파이로 영구 참여시킵니다.
대한민국 – NISK – KPOP FAN – 미디어는 현장에서 활동하지 않는 모든 친근한 요원과 협력합니다.
브라질 – ABIN – CARNAVAL – 한 줄의 오른쪽 또는 왼쪽 카드를 이동합니다.
'''오리지널 엔트리'''
게임에 대한 설명:
플레이어는 테러 위협을 뿌리뽑으려는 국가들의 비밀 서비스 역할을 맡는다. UUTE는 생지옥이었던 카라가 이끌고 있다. 카라는 오늘 세상을 지배하고 싶어해요 더 이상 선택의 여지가 없어. 그녀를 없애야만 해. 그렇지 않으면 그녀는 우리의 삶의 방식을 파괴할 거야. 이미 핵잠수함, 우주관제센터, 바이러스연구소, 유엔 고위관리가 납치된 유엔 등 전략영역에 침투했다. 이 장소들을 확보해서 인질을 구출해야 합니다. 누구를 믿어야 할지 모르겠군요 비밀 경호국은 테러리스트처럼 지하에서 행동해야 합니다 잠입자는 당신만의 서비스일 수 있습니다. 지하에서 행동하기 위해서는 우주 감시 위성을 활용하여 요원, 목표물, 전술적 또는 전략적인 장소를 찾고 작전을 통제하는 것이 최선이다.
규칙(참고: 규칙을 더 쉽게 이해하기 위해 보드 및 카드를 보려면 솔로 모드에서 게임을 시작하는 것이 좋습니다)
목표는 승점(VP)을 따내는 것이다. VP는 별 기호로 표시된 모든 카드의 하단에 표시됩니다. 플레이어는 목표(옐로우 카드), 보초(전사 사진), 요원(총으로 묶는 남자) 또는 카라 테러리스트(활을 든 흑인 여자)와 같은 카드를 캡처하여 부사장을 받습니다. 또한 플레이어는 자신의 에이전트를 이사회에 배치하여 VP를 받습니다. 게임은 교대로 진행됩니다. 모든 턴에서 모든 플레이어는 First Player 토큰을 들고 있는 플레이어부터 작업을 수행합니다. 게임은 12턴 이후에 종료되거나 합의된 목표 수(2~5개)가 캡처될 때 종료됩니다.
Board Board는 6행 7열로 구성되어 있습니다. 맨 위 행은 위성을 배치하기 위한 것입니다. 1행 – 맨 위 행 아래의 5행에는 경기 중에 실행되는 카드가 포함됩니다.
플레이어 시트 각 플레이어는 세 명의 친근한 에이전트(총, VP 및 보호막으로 플레이어 고유의 색으로 묶음), Super Satellite 토큰 및 선택적으로 Double Agent 토큰 또는 First Player 토큰이 포함된 시트를 받습니다. 각 플레이어 시트는 모든 턴에서 사용할 수 있는 특별한 힘을 제공하는 선택된 국가를 나타냅니다.
주사위, 노란색 큐브, 장비 카드 갑판 주사위는 공격 작업에 사용됩니다. 공격자는 4개의 주사위를 굴려 대상 방어와 결과를 비교합니다. 숫자가 같거나 높으면 성공입니다. 어떤 목표물은 방어력을 높이는 주사위를 하나 더 굴립니다. 노란색 큐브는 공격 시도 토큰입니다. 실패한 공격(또는 Binocular 항목 능력)을 위해 Objective 카드에 배치되고 다음 공격 롤 결과에 추가됩니다. 장비 데크는 보드를 새로 고치거나 특정 작업을 위해 그릴 다음 항목 카드를 표시합니다.
위성을 선택한 궤도(보드의 수직 행)에 배치하고 순서대로 배치(위성을 배치한 행에서 선택) 위성이 식별할 수 있는 보드의 카드를 사용하여 작업을 수행합니다.
위성 위성은 보드의 맨 위 행에 배치됩니다. 흰색 위성은 게임 엔진에 의해 배치됩니다. 첫 번째 턴에서 플레이어는 빈 곳에 인공위성을 자유롭게 배치합니다. 위성 단계 동안 플레이어는 두 가지 방법 중 하나로 위성을 재배치합니다. - 한 개의 위성을 다른 적/중립 위성과 교환 - 정확히 두 개의 위성을 다른 열에 있는 빈 슬롯에 재배치합니다.
인공위성에서는 각 위성마다 카드를 하나씩 보드 위에서 찾을 수 있습니다. 위성이 있는 같은 열에 카드를 선택해야 합니다. 지정된 열 플레이어의 위성 수(모든 색상)에 따라 열의 상위 1, 상위 2개 또는 상위 3개 행에서 선택할 수 있습니다. 동일한 색상의 위성 플레이어가 3개 있을 경우 이 열의 5개 행 중 하나를 선택할 수 있습니다.
카드 작업 어떤 카드가 표시되었는지에 따라 다음 작업을 수행합니다.
장비 카드(아이템 사진 포함) 카드를 플레이어 존으로 가져갑니다. 즉시 재생하거나 다른 턴을 실행할 수 있습니다. 특정 긍정적인 효과를 생성합니다.
친근한 에이전트 카드(총으로 묶는 사람, 플레이어 고유의 색상의 VP) 에이전트 VP 값이 플레이어 공격 값에 추가됩니다(현재 턴에만 해당).
적 에이전트 카드(총이 있는 남자, 다른 플레이어 색상의 VP) 또는 중립 에이전트 카드(총이 있는 남자, 검은색의 VP) 또는 카라 테러리스트 카드(활이 있는 여자, 검은색의 VP)를 캡처 또는 기타 액션을 표시했습니다. 방패에 표시된 숫자 + 다이 롤 1개입니다.
Sentinel 카드(병사 사진, 검은색 VP) Sentinel이 캡처 또는 기타 작업을 표시했습니다. 방패에 그의 방어 번호가 표시되어 있다.
특수 액션 카드(빨간 카드) 특정 효과를 생성합니다. 카드에 따라 다름 - 즉시 또는 턴 종료
목표 카드(옐로우 카드) - 즉시 특정 효과를 발생시키거나(캡쳐 표시) - 목표 방어가 방패에 표시된 번호입니다.
Capture (attack) action common 시퀀스는 다음과 같습니다. - player marks friendly agent, attack value에 VPs 추가 - 선택적으로 공격 값을 더 늘리는 작업(특정 항목 또는 목표 활성화) - marks target for capture - 공격 액션을 선택합니다. 4개의 디바이스가 attack value에 롤링되어 attack value에 추가됩니다. 총 데이터 수
70a9de90c570ef5cff5934304b1ddc15815ede13
The Boss
0
46
1268
906
2021-08-13T18:56:45Z
Ananstarsha
7468
/* Description */
wikitext
text/x-wiki
== Goal ==
At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand.
Be the player with the most money at the end of the game!
진행
라운드 준비
1.딜러는 카드 섞고 색깔별로 하나씩 빼서 해당 보스카드 밑에 앞면 안보이게 넣어둔다.
2.남은 카드 다시 섞고 골고루 나눠준다. 뒷면 색깔은 노출돼도 괜찮다.
이제 라운드 시작.
딜러부터. 왼쪽으로 진행
자기 차례때 다음 두 액션을 순서 상관없이 실행
1.도시 배치 (안해도 된다) ; 한곳에 마음껏. 그곳 남들것보다 더 많게. 작은큐브는 큰놈과 함께.
*시카고에 배치는 다른 도시에 먼저 배치한 뒤부터 가능하다.
2.정보 공개 (꼭 해야 된다) 손의 도시카드 한장 내려놓기.모두 손에 카드 한장만 남으면 마지막 라운드.
마지막 라운드 시작 전
1.턴 순서 바꾸기 ; 손에 큐브 많이 남은 사람부터. 동수면 딜러에서 시계방향 가까운 사람부터
2.다음 경찰카드 공개 ; 같은색 뱃지 3개 되면 이번 라운드로 게임 끝.
라운드 종료
큐브 가장 많아 도시 장악한 사람은 보스카드 아래에 뒷면으로 있는 도시카드 가져와서 적용
-돈주머니 점수 나오면 점수판 전진
-권총; 큰큐브 하나 게임에서 제거 / 감옥; 2라운드 쉬기 / 병원; 1라운드 쉬기 / X표; 신시내티에 추방토큰 놓고 앞으로 내내 거기 큐브 못놓음
*시카고 장악한 사람은 왼쪽편(숫자 낮은 방향) 도시들 놓여진 맨위 카드 점수들 합산 절반(내림) 먹는다.
다음 라운드 준비 (경찰뱃지 3개 안됐으면)
큰 큐브 내 손으로 돌아오고 작은 큐브는 제거
*시카고 빅보스카드 한칸 옆으로 (숫자 큰 방향) ; 제일 끝으로 가면 거기 계속 머문다.
선 딜러버튼 시계방향으로
종료
3번째 경찰뱃지 나오면 라운드 종료후 점수 계산
동률시 마지막 라운드에서 점수 더 딴 사람 승리
이것도 동률시 손에 큐브 더 많이 남은 사람 승리
이것도 동률시 승자 가리기 위해 한 라운드 더.
== Beginner Tips ==
*Give out useless information early and hold on to your gangsters until seeing what your opponents are planning.
*If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail.
3a84b02c1d2d13dbc63d7fc8ddd5f8b3faefa2e3
Gamehelpautomobiles
0
194
1269
2021-08-13T20:50:26Z
Ananstarsha
7468
새 문서: 기어 및 마모 큐브 이 큐브는 게임마다 똑같습니다. 3단 기어(흰색) - 보드의 흰색 공간으로 이동할 수 있습니다. 4단 기어(연한 회색) -...
wikitext
text/x-wiki
기어 및 마모 큐브
이 큐브는 게임마다 똑같습니다.
3단 기어(흰색) - 보드의 흰색 공간으로 이동할 수 있습니다.
4단 기어(연한 회색) - 보드의 연한 회색 공간으로 이동할 수 있습니다. 연한 회색 공간은 일반적으로 흰색 공간보다 길기 때문에 3단 기어 큐브보다 강력합니다.
5단 기어(진한 회색) - 보드의 진한 회색 공간으로 이동할 수 있습니다. 일반적으로 진한 회색 공간은 흰색 및 연한 회색 공간보다 길기 때문에 3단 및 4단 기어 큐브보다 강력합니다.
6단 기어(검은색) - 보드의 검은색 공간으로 이동할 수 있습니다. 블랙 스페이스가 가장 길어서 가장 강력한 큐브입니다.
마모(갈색) - 일반적으로 당신은 주머니에 마모 큐브가 있는 걸 원하지 않습니다. 강력한 카드와 고속 주행 시 착용감이 높아지므로 계속 분리할 수 있는 조치를 취해야 합니다. 그렇지 않을 경우 감당하기 어려울 수 있습니다!
기타 큐브
나머지 5개의 큐브는 게임마다 다른 동작을 할 수 있습니다. 각 게임에서 카드는 각 큐브 색상의 기능을 결정하는 데 사용되며, 큐브를 플레이하면 동일한 색상의 카드에 액션이 수행됩니다.
게임에 사용되는 카드는 미리 선택된 세트에서 나오거나 랜덤일 수 있습니다.
차량정비(노란색) - 차량정비 카드는 일반적으로 큐브 공급을 관리하는 데 사용됩니다.
핸들링(빨간색) - 핸들링 카드는 일반적으로 이동 보너스를 지급하기 위해 사용됩니다.
피트(보라색) - 피트 카드는 일반적으로 소유한 큐브를 제거하는 데 사용됩니다. 특히 큐브를 착용하는 경우입니다.
엔진(파란색) - 엔진 카드는 일반적으로 차량을 상당한 거리를 전진시킵니다.
성능(녹색) - 성능 카드가 게임에 큰 영향을 미칠 수 있으며, 종종 필드 뒤쪽에 있는 플레이어를 선호합니다.
SETUP
게임은 참가자 중에서 출발 순서를 무작위로 선택하게 됩니다.
각 플레이어는 3단 기어(화이트), 4단 기어(연한 회색), 차고(핸들링) 큐브의 작은 풀로 시작합니다.
각 플레이어는 게임 시작 전에 큐브를 추가로 구매할 수 있는 기회를 갖게 됩니다. 출발선에서 뒤쪽에 있는 플레이어는 큐브에 쓸 돈이 조금 더 많아진다.
일반적인 턴- 레이싱
Action Phase
당신의 active더미에서 한 개 이상의 큐브를 선택합니다. 한
개씩 used더미에 놓으면서, 그것의 효과를 적용합니다. 적절하게
큐브를 트랙에서 이동합니다.
원한다면 전체 턴을 건너뛰고 Pit Stop을 할 수 있습니다.
Pit Stop을 수행하면 Action Phase, Buy Phase 또는 Movement Phase는 수행되지 않지만 active 더미의 모든 마모를 제거합니다.
Buy Phase
active더미에서 남은 큐브를 돈으로 사용하여 큐브를 한 개 이
상 구매하고, 구매한 큐브는 used더미에 둔다.
Car Phase
액션으로 놓은 큐브에 따라 당신의 레이싱카를 트랙에서 움
직입니다.
Decline Phase
당신이 이동한 트랙 공간에서 가장 높은 단계에 해당하
는 마모 큐브를 얻습니다.
흰색 -> 1 마모 큐브
연한 회색 -> 2 마모 큐브
진한 회색 -> 3 마모 큐브
검은색 -> 4 마모 큐브
하지만! Decline Phase에서는 마모를 피할 수 있습니다.
드래프팅
당신이 다른 상대방의 레이싱카의 바로 후방 '칸'이나'구획'에서 이
번 턴 이동을 종료했다면, 드래프팅을 할 수도 있습니다. 만약 드래
프팅을 한다면, 당신은 이번 턴에서 이동한 공간의 색깔이 어떻든,
전혀 마모 큐브를 얻지 않습니다. 드래프팅은 훌륭합니다!
End Phase
active더미, 트랙, used더미에 있는 모든 큐브를 discard더
미로 옮깁니다. 그 후 7개의 새 큐브를 무작위로 주머니에서 뽑아
active더미에 놓습니다(모자랄 경우에만, discard더미에 있는 모든
큐브를 당신의 주머니에 넣습니다).
THE END OF THE GAME
한 플레이어의 구간 마커가 마지막 구간에 있고, 그의 레이싱카가
결승선을 통과했다면, 현재 라운드가 끝난 후에 게임을 종료합니
다. 즉 모든 플레이어는 같은 횟수로 턴을 가집니다. 결승선을 가
장 멀리 통과한 레이싱카의 주인이 승리자입니다. 동일하다면, 트
랙에서 가장 안쪽 차선을 달린 레이싱카가 승리합니다.
QUICK SUMMARY OF A TURN
Action Phase
To start with, you will have drawn 7 cubes and these will form your Active pile.
You can play as many cubes as you like from your Active pile, one at a time, to use the effect shown on their matching card.
When you play a cube, it moves from your Active pile to your Used pile.
Your car never moves during the Action phase, but where playing a cube will move your car, you place the cube onto the board in the appropriate space, planning out your move. Your car will move along the planned route at the end of the turn.
If you wish, you can skip your entire turn and have a Pit Stop. If you take a Pit Stop, you will not perform the Action Phase, Buy Phase or Movement Phase, but you will remove all wear from your Active pile.
Buy Phase
In the Buy phase, you add up the Value (the yellow dollar signs) of any cubes that you have not played and are still in your Active pile. You may then spend that money to buy any number of cubes.
Any money unspent does not carry over until later turns.
Car Phase
This is where you car actually moves. If you have placed any cubes on the board in the Action phase, your car will move to the last cube that you placed.
Decline Phase
If your car moved this turn, you will gain wear cubes.
The number that you get will be based on the color of the darkest space your car moved into or through this turn.
White -> 1 Wear cube Light Gray -> 2 Wear cubes Dark Gray -> 3 Wear cubes Black -> 4 Wear cubes
BUT! Wear in the Decline phase can be avoided. If you finish your move immediately behind another car then you are drafting, and will receive no Wear from movement this turn. You will still receive Wear described on action cards whose cubes you played during the Action phase.
End Phase
This is the cleanup phase. All cubes on your board and on the track are moved into your Discard pile.
You then randomly draw 7 new cubes from your bag and put them into your Active pile for next turn.
If your bag is emptied before you have drawn 7 cubes, all cubes from your Discard pile are returned into your bag.
THE END OF THE GAME
A race lasts a number of laps chosen at the beginning of the game.
All players will have the same number of turns, so the game will end after the final player's turn if anyone has completed the required number of laps and crosses the finish line.
Once at least someone has finished the race and all players have had the same number of turns, the winner is the car that has travelled the furthest, so even if you cross the finish line first it is worth travelling as far as you can before you turn ends.
ADVANCED RULES
Once you have played the basic game, there are additional rules you may choose to explore.
Weaving
Normally, cubes are simply placed on spaces during your Action phase, and if a space is made up of multiple segments then the cube is placed as far forward as is available.
If you use the Weaving option, then cubes can be placed anywhere within a square. This allows you to "cut across" a space by landing on one of the squares further back in order to reach a space on the far side before it disappears.
The result is movement where there a far more options for each move (making moves far less simple to plan) but providing for more sophisticated movement paths.
Driver Cards
If you play with Driver Cards, then before play begins, each player will be able to choose one driver who will grant them a unique ability they can use each turn throughout the game.
Seasons
A Season is a game made up of a series of 3 or more races, with points being awarded for each race.
Between races, players may choose a Sponsor to give them a unique advantage that will modify their cube pool.
The winner of a race has first choice from the pool of available Sponsors. A player may keep their Sponsor from the previous race if they have one, instead of taking a new one. If they do so, they must choose to discard one of the existing available Sponsors.
The starting positions in the first race are random as usual, but from the second race onwards players will start based on their finishing position in the previous race.
Action Card Clarifications
3rd Gear
Move 1 white space
Place this white cube on a white space on the track. This white space must be adjacent to your race car, or adjacent to the last cube previously placed on the track earlier this turn.
4th Gear
Move 1 light gray space
Place this light gray cube on a light gray space on the track. This light gray space must be adjacent to your race car, or adjacent to the last cube previously placed on the track earlier this turn.
5th Gear
Move 1 dark gray space
Place this dark gray cube on a dark gray space on the track. This dark gray space must be adjacent to your race car, or adjacent to the last cube previously placed on the track earlier this turn.
6th Gear
Move 1 black space
Place this black cube on a black space on the track. This black space must be adjacent to your race car, or adjacent to the last cube previously placed on the track earlier this turn.
Wear
Place this cube from your used pile into your discard pile
In general, you do not want wear cubes in your bag. This effect gets you a step closer to removing it, by allowing you to place it directly into your discard pile. Keep in mind, only wear cubes originating from your active pile may use this effect.
Car Chief (Garage)
Remove 1 gear cube from your discard pile. Gain 1 gear cube of 1 gear higher.
Remove any white, light gray, dark gray, or black gear cube from your discard pile. If you removed a white cube, then gain a light gray cube. If you removed a light gray cube, then gain a dark gray cube. If you removed a dark gray cube, then gain a black cube. If you removed a black cube, then you don’t gain anything.
Engineer (Garage)
Place up to 3 cubes from your active pile into your discard pile. Then remove the same number of cubes from your discard pile.
Choose up to 3 cubes from your active pile. Place the chosen cubes into your discard pile. If you chose 1 cube, then remove 1 cube from your discard pile. If you chose 2 cubes, then remove 2 cubes from your discard pile. If you chose 3 cubes, then remove 3 cubes from your discard pile. Keep in mind, the removed cubes may be the very cubes you just placed in your discard pile.
Manager (Garage)
May remove 1 cube from your active pile AND/OR Put 1 cube from your active pile or discard pile back into your bag.
You have the option of removing a cube from your active pile. Whether you opt to remove a cube or not, you may choose 1 cube from your active pile, or your discard pile, and place it back into your bag.
Mechanic (Garage)
Place 1 other cube from your active pile into your used pile. Then remove up to 2 cubes from your discard pile.
Choose a cube from your active pile and place it in your used pile. This chosen cube’s effect will not be applied. Then remove up to 2 cubes from your discard pile.
Factory Support (Garage)
Draw 1 cube. Remove 1 cube from your active pile or discard pile.
Draw 1 cube from your bag. After this, you must remove 1 cube from your active pile or discard pile. Keep in mind, the 1 removed cube may be the cube you just drew out of your bag.
Maintenance Staff (Garage)
Remove any number of cubes from your active pile. Then remove up to twice that amount from your discard pile.
Choose any number of cubes to remove from your active pile. These cubes can be any combination of cubes, including but not limited to, wear cubes. Then you may remove up to twice that amount of cubes from your discard pile. For example, if you removed 3 cubes from your active pile, you may remove up to 6 cubes from your discard pile.
Performance Testing (Garage)
Remove this cube. Then draw up to 3 cubes.
First, you must remove this very cube. Then, you may draw up to 3 cubes from your bag.
Aerodynamics (Handling)
During your Decline Phase this turn, you are considered drafting and will not take any wear during that phase.
When you get to the Decline Phase of your turn you will not gain any wear despite what color spaces you moved on, because you are considered to be drafting. Note that this card does not prevent you from gaining wear cubes during your Action Phase.
Steering (Handling)
Gain 1 wear. Discard 1 gear from your active pile. Move up to 3 spaces of the color 1 lower than the discarded gear.
Gain 1 wear cube from the stock. Then choose 1 gear cube from your active pile to place into your discard pile. Move your red cube up to 3 spaces on the board matching the color 1 lower than the chosen gear cube. For example, if you chose to discard a black cube from your active pile, then you could move up to 3 consecutive dark gray spaces with your red cube. Note: the chosen gear cube stays in your discard pile.
Suspension (Handling)
Gain 1 wear. Move 1 space matching 1 gear in your discard pile.
Gain 1 wear cube from the stock. Then place your red cube onto a space on the board matching the color of a gear cube in your discard pile. For example, if you have a dark gray cube in your discard pile, then you could move on a dark gray space with your red cube. Note, the matching gear cube stays in your discard pile.
Tires (Handling)
Select 1 gear in your active pile. Move 1 space on any color lower than the selected gear.
Place your red cube onto a space on the board matching any color lower than a gear cube in your active pile. For example, if you have a dark gray cube in your active pile, then you could move on a light gray space or a white space with your red cube. Note, the matching gear cube stays in your active pile.
Burnout (Handling)
Gain 1 wear. Select 1 gear cube in your discard pile. Move up to 2 spaces of the color 1 lower than the selected gear.
Gain 1 wear cube from the stock. Then choose 1 gear cube in your discard pile. Move your red cube up to 2 spaces on the board matching the color 1 lower than the chosen gear cube. For example, if you chose a black cube in your discard pile, then you could move up to 2 consecutive dark gray spaces with your red cube. Note, the chosen gear cube stays in your discard pile.
Camber & Toe (Handling)
Discard 1 gear cube from your active pile. Move 1 space on any color.
Choose 1 gear cube from your active pile to place into your discard pile. Then, move your red cube 1 space on any color on the board. For example, if you chose to discard a light gray cube from your active pile, then you could move on white, light gray, dark gray, or black with your red cube. Note, the chosen gear cube stays in your discard pile.
Redline (Handling)
During your Action Phase, you may use white gear cubes to move on any color space. Gain 1 wear for each white gear cube used this way.
During your Action Phase, you may use any number of white gear cubes that you have in your active pile as if they were any color gear cube. Place these white gear cubes onto the board on color(s) of your choice. Use 1 white gear cube per space. Gain 1 wear cube from the stock for each white cube that you used with this effect.
Crew Chief (Pit)
Draw cubes until you draw 1 non-wear. Then remove all wear from your discard pile.
Draw 1 cube from your bag. If you draw a wear cube, then draw again. Stop drawing cubes when you draw any cube other than a wear cube. After this, remove all wear cubes from your discard pile. Keep in mind any wear cubes that you drew during this card’s effect will not be able to be removed with this card’s effect, since those wear cubes are placed in your active pile, not your discard pile.
Pit Captain (Pit)
Remove up to 6 cubes from your discard pile.
Choose up to 6 cubes to remove from your discard pile. These cubes can be any combination of cubes including, but not limited to, wear cubes.
Pit Crew (Pit)
Either remove all wear from your discard pile, OR remove any 2 cubes from your discard pile.
Choose one of the following. You may either remove all of the wear cubes in your discard pile, or you may remove any 2 cubes of your choice from your discard pile including, but not limited to, wear cubes.
Pit Team (Pit)
Remove up to 3 cubes from your discard pile. Then gain 1 new cube costing less than, or equal to, the total cost of the removed cubes.
Choose up to 3 cubes to remove from your discard pile. These cubes can be any combination of cubes including, but not limited to, wear cubes. Add the costs, not the value, of the removed cubes. Use that total cost as money to buy exactly 1 cube from the stock. After this, any leftover money gained from this card’s effect is lost.
Air Jacks (Pit)
Remove as many cubes from your discard pile as you have unique colors in your discard pile.
Count how many unique colors of cubes you currently have in your discard pile. Then remove up to that many cubes from your discard pile. For example, if you had 1 yellow cube, 2 dark gray cubes, 3 blue cubes, 1 green cube, and 2 wear cubes in your discard pile, then you could remove up to 5 of those cubes.
Impact Wrench (Pit)
Remove up to 4 cubes from your discard pile. Then remove all wear from your used pile.
Choose up to 4 cubes to remove from your discard pile. These cubes can be any combination of cubes, including but not limited to, wear cubes. Then, remove all wear cubes currently in your used pile. This means all wear cubes gained during your Action Phase up to this point, including those placed on the track, are removed. Keep in mind, this does not allow you to remove wear gained by any future action, nor does it allow you to ignore gaining wear during your Decline Phase.
Pit Mechanic (Pit)
Remove up to 6 wear from your discard pile. Then, if you have fewer cubes in your discard pile than all other players' discard piles, remove up to 2 more cubes of any color.
Remove up to 6 wear cubes from your discard pile. After this, count how many cubes you currently have in your discard pile. Compare your total with each other player individually, not all other players as a group. If you have less cubes in your discard pile than each of the other players’ discard piles, you get to remove up to 2 additional cubes from your discard pile. These additional cubes can be any combination of cubes, including but not limited to, wear cubes. For example, if you had 5 cubes left in your discard pile after removing up to 6 wear cubes, then you could remove up to 2 more cubes as long as no other player had 5 or fewer cubes in their discard pile.
Diesel Engine (Engine)
Gain 2 wear. Move up to as many dark gray spaces as you have dark gray cubes in your discard pile.
Gain 2 wear cubes from the stock. Count how many dark gray cubes you currently have in your discard pile. Then move your blue cube up to that many consecutive dark gray spaces on the board. For example, if you had 3 dark gray cubes in your discard pile, then you could move up to 3 consecutive dark gray spaces with your blue cube.
Hybrid Engine (Engine)
Gain 1 wear. If you have more blue cubes on your player sheet than in any other player's discard pile, move up to 2 spaces in any 1 color.
Gain 1 wear cube from the stock. Count how many blue cubes you currently have in your active pile, used pile, and discard pile collectively. Compare that total against blue cubes found in each other player’s discard pile. Make this comparison with each other player individually, not all other players as a group. If you have more than any other player, then move your blue cube up to 2 consecutive spaces on the board. These 2 spaces must be the same color. For example, if you had 1 blue cube in your active pile, 1 on the track, and 2 blue cubes in your discard pile, then you could move 2 spaces of any color as long as no other player had 4 or more blue cubes in their discard pile.
Rotary Engine (Engine)
Gain 1 wear. Move up to as many white spaces as you have unique colors in your discard pile.
Gain 1 wear cube from the stock. Count how many unique colors of cubes you currently have in your discard pile. Then move your blue cube up to that many consecutive white spaces on the board. For example, if you had 1 white cube, 3 light gray cubes, 1 blue cube, and 2 wear cubes in your discard pile, then you could move up to 4 consecutive white spaces with your blue cube.
Supercharged (Engine)
Gain 1 wear. Place up to 2 cubes from your discard pile to your active pile.
Gain 1 wear cube from the stock. Choose up to 2 cubes in your discard pile. Place these chosen cubes into your active pile.
Crate Motor (Engine)
Move up to 3 spaces on any 1 color. Then after your End Phase, each other player in a lower position than you may move 1 space on any color.
Move your blue cube up to 3 spaces on any 1 color on the board. Then, after your End Phase, determine what position in the race each player’s race car is currently in. Each player that is in a lower position in the race than you, may move 1 space on any color. This movement takes place in position order, not turn order, and those other players do not gain wear for their movement. Additionally, after each player moves, including you, momentum must be updated and positions may change due to this momentum. Keep in mind, if more than one of these blue cubes is used in a single turn, player positions are not determined until after your End Phase. In this situation, each player in a lower position moves all awarded spaces before moving onto the next player. For example, if you used 2 blues cubes this turn, and ended up in 1st position after your End Phase, the player in 2nd position would get to move up to 2 spaces on any color(s) without gaining any wear. After the 2nd position player moved, and momentum updated, then the 3rd position player would move up to 2 spaces on any color(s), and so on.
Fuel Injection Engine (Engine)
Gain 2 wear. During your Action Phase, each of your gear cubes moves twice as many spaces as they normally do.
Gain 2 wear cubes from the stock. During your Action Phase this turn, each of your activated gear cubes may move twice as many spaces as they would normally move. This means that for each gear cube that you use this turn, you may move 2 spaces instead of 1 on its respective color. Keep in mind, this effect can combine with cards like Redline, but does not have any effect on cards like Camber & Toe. Furthermore, activating more than one of these blue cubes is superfluous, as it does not compound the effect.
Internal Combustion Engine (Engine)
Discard 1 cube from your active pile. Then place up to 3 cubes from your discard pile into your active pile. Gain 1 wear for each cube placed this way.
Choose 1 cube from your active pile to place into your discard pile. Then choose up to 3 cubes from your discard pile. Place these chosen cubes into your active pile. Gain 1 wear cube from the stock for each cube that you brought from your discard pile to your active pile with this effect. Keep in mind, one of the cubes that you bring from your discard pile back to your active pile may be the very cube you just placed in your discard pile.
Boost (Performance)
Draw up to 3 cubes. Gain 1 wear for each cube drawn. All other players may draw 1 cube.
Draw up to 3 cubes from your bag. You may draw these cubes one at a time and may stop when satisfied. Gain 1 wear cube from the stock for each cube that you drew. After this, all other players have the choice to draw 1 cube from their bag or not. The other players do not gain wear for this.
Gearbox (Performance)
Gain 1 wear. Move up to as many light gray spaces as your current position in the race. If in last position, you may move 1 additional light gray space.
Gain 1 wear cube from the stock. Determine what position in the race your race car is currently in. Remember, your position is always determined by where your race car is at the beginning of the Action Phase, not where it will be during your Car Phase. If tied for a position, the innermost lane is leading. Then move your green cube up to that many consecutive light gray spaces on the board. You may move 1 more light gray space, if you are currently in last place. For example, if your race car is currently in 3rd place of a 4 player game, then you could move up to 3 consecutive light gray spaces with your green cube. Alternatively, if you were in 4th place of a 4 player game, then you could move up to 5 consecutive light gray spaces.
Nitro (Performance)
Draw 2 cubes. Place 1 in your active pile and the other in your discard pile.
You must draw exactly 2 cubes from your bag. After drawing these 2 cubes, choose 1 to place in your active pile and 1 to place into your discard pile.
Turbo (Performance)
Gain 2 wear. Move up to 2 light gray spaces. Then move up to 1 light gray space for each green cube that every player collectively has in their discard piles.
Gain 2 wear cubes from the stock. Move your green cube up to 2 consecutive light gray spaces on the board. Then you may continue moving up to 1 more light gray space for each green cube that every player, including you, has in their discard piles. For example, if you had 2 green cubes in your discard pile, and two other players had 1 green cube each in their discard piles, then you could move up to 6 consecutive light gray spaces with a green cube from your active pile.
Adrenaline (Performance)
Move 1 light gray space OR during your Car Phase move up to 2 light gray spaces per position you advanced this turn.
Choose one of the following. You may either move your green cube 1 light gray space OR during your Car Phase this turn, you may move up to 2 light gray spaces per position you advanced. In order to do the second option, take note of what position in the race your race car is in at the beginning of your Car Phase. Then note what position your race car ends up in at the end of your Car Phase. Finally, move up to 2 light gray spaces per position you advanced. For example, if you chose the second option and started your Car Phase in fourth position of a 5 player game, but ended your Car Phase by passing 2 other cars to move into second Position. Then you could move up to 4 light gray spaces.
Bump & Run (Performance)
Gain 1 wear. If not in first position, move up to 2 dark gray spaces. if in last position, you may move one additional dark gray space.
Gain 1 wear cube from the stock. Determine what position in the race your race car is currently in. Then, as long as you are not in first position, move your green cube up to 2 dark gray spaces on the board. If you are currently in last place, you may move 1 more dark gray space. For example, if your race car is currently in 4th place of a 4 player game, then you could move up to 3 consecutive dark gray spaces with your green cube.
Overdrive (Performance)
Gain 1 wear. According to your current position in the race, move up to 3 spaces on the following color or lower: First = white, Last = dark gray Other = light gray
Gain 1 wear cube from the stock. Determine what position in the race your race car is currently in. Then, move your green cube up to 3 spaces according to your position. If you are in first place, move on white. If you are in last place, move on dark gray or lower. For all other positions in the race, move on light gray or lower. Keep in mind, you may move on more than 1 color with each green cube. For example, if your race car is currently in 2nd place of a 3 player game, you could move 1 white space and 2 light gray spaces with 1 green cube.
Driver Card Clarifications
01 - Josh Trin
For each wear gained during your Decline Phase, move up to 1 light grey space.
During your Decline Phase, you may move your race car up to 1 light gray space for each wear you gained. Keep in mind, this is only for wear gained during your Decline Phase, not your Action Phase. For example, if you gained 3 wear during your Decline Phase, then you can move up to 3 light gray spaces. For another example, if you would have gained 2 wear during your Decline Phase, but ended up drafting, you will not get a benefit from this driver.
02 - David Bird
Place 1 cube from your discard pile into your active pile.
During your Action Phase, you may choose 1 cube from your discard pile. Place this chosen cube into your active pile. That cube may now be used like any other cube in your active pile.
03 - Eileen Pi
Place up to 3 cubes from your discard pile into your bag.
During your Action Phase, you may choose up to 3 cubes from your discard pile. These chosen cubes can be any combination of colors. Place these chosen cubes back into your bag.
04 - Mag Matthews
Draw up to 3 cubes at once. For each cube drawn, choose one: remove it, place it in your active pile, or put it back into your bag.
During your Buy Phase, you may draw up to 3 cubes at once. After you have drawn all required cubes, decide to do one of the following options with each cube: remove it by putting it back in stock, place it in your active pile, OR put it back into your bag. You may decide to do any of the three options with each cube. Keep in mind, any cube added to your active pile may only be used for its value to buy new cubes, since you are in your Buy Phase.
05 - Kali Farmer
Remove any number of cubes from your discard pile. Pay \$1 for each cube removed.
During your Buy Phase, you may remove any number of cubes from your discard pile. These removed cubes can be any combination of cubes, including but not limited to, wear cubes. For each cube that you decide to remove this way, you must pay $1. If you have no money during your Buy Phase, you will not get a benefit from this driver.
06 - Juan Goody
At the end of the Car Phase, move 1 space on any color.
During your Car Phase, after you finish your normal move with your race car, you may move 1 additional space on any color. Like normal, you could be subject to wear for this movement during your Decline Phase, if you don’t end up drafting.
07 - Mike Skipjack
For each wear gained during your Decline phase, draw up to 1 additional cube during your End Phase.
During your Decline Phase, take note of how many wear cubes you gained. For each of those wear cubes, you may draw up to 1 additional cube during your End Phase. For example, if you gained 3 wear during your Decline Phase, then you will draw 10 cubes during your End Phase, instead of just 7. This means, you will start your next turn’s Action Phase with those 10 cubes. If you gained no wear during your Decline Phase, for instance if you ended up drafting, you will not get a benefit from this driver.
08 - Micah Conner
Before drawing, remove up to 3 wear from your player sheet.
During your End Phase, before drawing new cubes for your active pile, you may remove up to 3 wear cubes from your player board. Keep in mind, these wear cubes can be located in any pile on your player board or on the track.
09 - Nathan Emery
After drawing, draw up to 2 more cubes.
During your End Phase, after drawing new cubes for your active pile, you may draw up to 2 additional cubes. Of course, these cubes may be used like any other cube in your active pile.
10 - Kaia Lin
After drawing, discard any number of cubes. Draw cubes equal to the number you discarded.
During your End Phase, after drawing new cubes for your active pile, you may choose any number of those cubes to place in your discard pile. Then, draw cubes equal to the number that you chose to discard. You may only do this once. For example, after drawing 7 cubes for your active pile, you could decide to discard 4 cubes, so that you can draw 4 new cubes to add to your active pile.
Sponsor Clarifications
Sponsors A1-A3
Spend the specified amount of money to buy new cubes from the stock. Keep in mind, the stock does not replenish from race to race during the season, so some cubes may be in short supply. Any money not spent is lost.
Sponsors B1-B3
Remove the specified amount of additional cubes from your bag and/or player board. These cubes can be any combination of cubes, including but not limited to, wear cubes.
Sponsors C1-C3
Remove the specified amount of wear cubes from your bag and/or player board. These cubes must be wear cubes.
Sponsors D1-D3
Gain the specific cubes stated from the stock for free. If the stock does not have adequate supply, then take as many as available.
Sponsors E1-E3
Take note of how many non-wear cubes you removed with your sponsor’s standard remove ability. Then, for each non-wear you removed, remove up to 4 wear cubes from your bag and/or player board. For example, if you had Sponsor E1, finished in first position, and decided to remove 2 white cubes and 1 wear cube, then you’d be allowed to remove up to 8 wear cubes from your bag and/or player board.
Note: Sponsor E3’s last place effect does not have an ability beyond its standard remove ability.
Sponsors F1-F3
Remove the specified amount of additional cubes from your bag and/or player board. Then, for each additional cube removed, you may spend up to $2. For example, if you had Sponsor F2, and finished 3rd in a 4 player game, then using the middle place effect would let you remove up to 3 additional cubes. If you removed all 3 additional cubes, then you’d be able to spend $6. Any money not spent is lost.
fa0e28583227a63518f76c2866c287ab8bbece5e
Gamehelpnothanks
0
184
1270
1245
2021-08-15T02:19:12Z
EBLCar
7473
wikitext
text/x-wiki
개요
노땡스의 목적은 모든 카드가 회수되었을 때 가장 적은 점수를 얻는 플레이어가 되는 것입니다. (보드게임 아레나에선 점수가 음수입니다)
준비 <br>
각각의 플레이어는 11개의 칩을 받습니다. 3~35숫자 카드 중에서 9장의 카드는 랜덤으로 덱에서 제거됩니다. 덱의 맨 윗 카드는 보여집니다.<br>
플레이하기<br>
당신의 턴에, 당신은 칩을 소비하거나 더미에 있는 모든 칩과 카드를 가져갑니다. 만약에 칩을 소비하면 턴은 종료됩니다. 카드를 가져가면, 다음 카드가 보여지고 당신의 턴이 계속됩니다.
게임은 마지막 카드가 가져가지면 종료됩니다.<br>
점수 매기기<br>
점수는 카드 숫자에서 당신이 가진 칩의 갯수를 뺀 것의 총합입니다. 하지만, 만약 연속되는 숫자의 카드를 가지고 있다면, 오직 가장 낮은 숫자만 점수에 더해집니다.
예시 : 5개의 칩과 카드 3, 10, 11, 12, 13, 20이 있다면, 점수는 3+10+20-5=28 입니다.
<br>
<br>
가장 낮은 점수를 가진 플레이어가 승자입니다.
5bc76a2cd54fb4ee9e40d722691cddf12e665940
Gamehelpkoikoi
0
195
1271
2021-09-17T09:50:29Z
Nilzzzzy
7482
코이코이 설명 작성
wikitext
text/x-wiki
=코이코이=
코이코이는 일본에서 가장 많이 하는 화투 게임 중 하나입니다. 화투는 한 해의 12개월에 따라 자연을 묘사한 일본의 전통 카드 묶음입니다.
자기 손이나 카드 더미에서 바닥에 깔린 패와 같은 달의 패를 내야 패를 가져와 (특정 조합을 구성해 점수를 내는 족보인) 역을 만들 수 있습니다.
역을 만들면 멈추고 그 시점의 점수를 획득하거나, '코이코이'를 선언하고 계속 진행해 보다 강력한 역의 완성을 시도할 수 있습니다.
31e83a2843c5a48cdd843c21e8277715d91506d8
1272
1271
2021-09-17T10:13:12Z
Nilzzzzy
7482
wikitext
text/x-wiki
=코이코이=
코이코이는 일본에서 가장 많이 하는 화투 게임 중 하나입니다. 화투는 한 해의 12개월에 따라 자연을 묘사한 일본의 전통 카드 묶음입니다.
자기 손이나 카드 더미에서 바닥에 깔린 패와 같은 달의 패를 내야 패를 가져와 (특정 조합을 구성해 점수를 내는 족보인) 역을 만들 수 있습니다.
역을 만들면 멈추고 그 시점의 점수를 획득하거나, '코이코이'를 선언하고 계속 진행해 보다 강력한 역의 완성을 시도할 수 있습니다.
==게임방법==
2명의 플레이어는 각각 8장의 패를 들고 바닥에도 8장의 패를 깔고 시작합니다.
2명의 플레이어는 각각 한턴씩 진행하는 방식이다.
각각의 턴에서 패에서 한장을 바닥에 내려놓고 패 뭉치에서 한장 집어서 바닥에 내려놓습니다.
내려놓는 카드와 바닥에 있는 카드가 같은 달의 패면 가져올 수 있습니다.
바닥에 두장의 같은 달의 패가 있을 때는 둘 중 하나만 가져옵니다.
바닥에 세장의 같은 달의 패가 있을 때는 모든 카드를 가져옵니다.
가져온 카드의 조합, 즉 역에 따라 점수를 획득할 수 있습니다.
28a53b00e56da920a7b9459414acfcae64265e94
1273
1272
2021-09-17T10:28:35Z
Nilzzzzy
7482
wikitext
text/x-wiki
=코이코이=
코이코이는 일본에서 가장 많이 하는 화투 게임 중 하나입니다. 화투는 한 해의 12개월에 따라 자연을 묘사한 일본의 전통 카드 묶음입니다.
자기 손이나 카드 더미에서 바닥에 깔린 패와 같은 달의 패를 내야 패를 가져와 (특정 조합을 구성해 점수를 내는 족보인) 역을 만들 수 있습니다.
역을 만들면 멈추고 그 시점의 점수를 획득하거나, '코이코이'를 선언하고 계속 진행해 보다 강력한 역의 완성을 시도할 수 있습니다.
==게임방법==
2명의 플레이어는 각각 8장의 패를 들고 바닥에도 8장의 패를 깔고 시작합니다.
2명의 플레이어는 각각 한턴씩 진행하는 방식이다.
각각의 턴에서 패에서 한장을 바닥에 내려놓고 패 뭉치에서 한장 집어서 바닥에 내려놓습니다.
내려놓는 카드와 바닥에 있는 카드가 같은 달의 패면 가져올 수 있습니다.
바닥에 두장의 같은 달의 패가 있을 때는 둘 중 하나만 가져옵니다.
바닥에 세장의 같은 달의 패가 있을 때는 모든 카드를 가져옵니다.
가져온 카드의 조합, 즉 역에 따라 점수를 획득할 수 있습니다.
==역의 종류==
게임중 아이콘을 누르면 역의 종류와 해당 역의 종류를 볼 수 있는 리스트가 나오며, 리스트의 최하단에 12개월의 패를 알수 있습니다.
fa9a6615c92c7bbcc09ff43ccacf3d284c32b29f
1274
1273
2021-09-17T10:50:12Z
Nilzzzzy
7482
완성(아마도) 근데 경험에 기초해서 만든거라 틀릴 수도 있음
wikitext
text/x-wiki
=코이코이=
코이코이는 일본에서 가장 많이 하는 화투 게임 중 하나입니다. 화투는 한 해의 12개월에 따라 자연을 묘사한 일본의 전통 카드 묶음입니다.
자기 손이나 카드 더미에서 바닥에 깔린 패와 같은 달의 패를 내야 패를 가져와 (특정 조합을 구성해 점수를 내는 족보인) 역을 만들 수 있습니다.
역을 만들면 멈추고 그 시점의 점수를 획득하거나, '코이코이'를 선언하고 계속 진행해 보다 강력한 역의 완성을 시도할 수 있습니다.
==게임방법==
2명의 플레이어는 각각 50 일본엽전을 가지고 시작합니다.
2명의 플레이어는 각각 8장의 패를 들고 바닥에도 8장의 패를 깔고 시작합니다.
2명의 플레이어는 각각 한턴씩 진행하는 방식입니다.
각각의 턴에서 패에서 한장을 바닥에 내려놓고 패 뭉치에서 한장 집어서 바닥에 내려놓습니다.
내려놓는 카드와 바닥에 있는 카드가 같은 달의 패면 가져올 수 있습니다.
바닥에 두장의 같은 달의 패가 있을 때는 둘 중 하나만 가져옵니다.
바닥에 세장의 같은 달의 패가 있을 때는 모든 카드를 가져옵니다.
가져온 카드의 조합, 즉 역에 따라 문(점수)을 획득할 수 있습니다.
==역의 종류==
게임중 아이콘을 누르면 역의 종류와 해당 역의 문을 볼 수 있는 리스트가 나오며, 리스트의 최하단에 12개월의 패를 알수 있습니다.
==기타==
1. 2명의 플레이어는 각각 50 일본엽전을 가지고 시작합니다.
2. 한 판의 게임은 6달(라운드) 또는 12달로 이루어져 있습니다.
3. 자신의 턴이 끝났을 때 문을 추가하는데 성공하면 코이코이나 쇼부를 선택할 수 있습니다.
쇼부를 선택하면 그 즉시 달의 진행이 끝나며 자신의 문만큼 상대의 일본 엽전을 가져올 수 있습니다.
코이코이를 선택하면 해당 달의 진행을 속행하며 다음 문 추가 때 코이코이선택 또는 쇼부를 선택할 수 있습니다.
4. 상대의 코이코이 이후 자신이 쇼부를 내어 달의 진행을 마무리할 경우 문이 두배가 되는데 이를 코이코이가에시(こいこい返し)라고 한다.
5. 쇼부를 내었을 때 7문이 넘으면 점수가 두배가 되는데 이를 바이츠케(倍付け)라고 한다.
6. 쇼부가 나지 않고 모든 플레이어가 패플 다 사용하면 먼저 시작한 플레이어가 승리하며 6문을 가져가느데 이를 친권이라고 한다.
7. 자신의 일본엽전을 모두 잃거나 게임이 종료했을 때 상대보다 일본엽전이 적으면 진다.
f597c031125d487b037b0e5eed29c70ca2df363f
1275
1274
2021-09-17T10:50:50Z
Nilzzzzy
7482
wikitext
text/x-wiki
=코이코이=
코이코이는 일본에서 가장 많이 하는 화투 게임 중 하나입니다. 화투는 한 해의 12개월에 따라 자연을 묘사한 일본의 전통 카드 묶음입니다.
자기 손이나 카드 더미에서 바닥에 깔린 패와 같은 달의 패를 내야 패를 가져와 (특정 조합을 구성해 점수를 내는 족보인) 역을 만들 수 있습니다.
역을 만들면 멈추고 그 시점의 점수를 획득하거나, '코이코이'를 선언하고 계속 진행해 보다 강력한 역의 완성을 시도할 수 있습니다.
=게임방법=
2명의 플레이어는 각각 50 일본엽전을 가지고 시작합니다.
2명의 플레이어는 각각 8장의 패를 들고 바닥에도 8장의 패를 깔고 시작합니다.
2명의 플레이어는 각각 한턴씩 진행하는 방식입니다.
각각의 턴에서 패에서 한장을 바닥에 내려놓고 패 뭉치에서 한장 집어서 바닥에 내려놓습니다.
내려놓는 카드와 바닥에 있는 카드가 같은 달의 패면 가져올 수 있습니다.
바닥에 두장의 같은 달의 패가 있을 때는 둘 중 하나만 가져옵니다.
바닥에 세장의 같은 달의 패가 있을 때는 모든 카드를 가져옵니다.
가져온 카드의 조합, 즉 역에 따라 문(점수)을 획득할 수 있습니다.
=역의 종류=
게임중 아이콘을 누르면 역의 종류와 해당 역의 문을 볼 수 있는 리스트가 나오며, 리스트의 최하단에 12개월의 패를 알수 있습니다.
=기타=
1. 2명의 플레이어는 각각 50 일본엽전을 가지고 시작합니다.
2. 한 판의 게임은 6달(라운드) 또는 12달로 이루어져 있습니다.
3. 자신의 턴이 끝났을 때 문을 추가하는데 성공하면 코이코이나 쇼부를 선택할 수 있습니다.
쇼부를 선택하면 그 즉시 달의 진행이 끝나며 자신의 문만큼 상대의 일본 엽전을 가져올 수 있습니다.
코이코이를 선택하면 해당 달의 진행을 속행하며 다음 문 추가 때 코이코이선택 또는 쇼부를 선택할 수 있습니다.
4. 상대의 코이코이 이후 자신이 쇼부를 내어 달의 진행을 마무리할 경우 문이 두배가 되는데 이를 코이코이가에시(こいこい返し)라고 한다.
5. 쇼부를 내었을 때 7문이 넘으면 점수가 두배가 되는데 이를 바이츠케(倍付け)라고 한다.
6. 쇼부가 나지 않고 모든 플레이어가 패플 다 사용하면 먼저 시작한 플레이어가 승리하며 6문을 가져가느데 이를 친권이라고 한다.
7. 자신의 일본엽전을 모두 잃거나 게임이 종료했을 때 상대보다 일본엽전이 적으면 진다.
35375374d2afe6663f8b8411488d054b88faa085
1279
1275
2021-09-19T06:55:27Z
Nilzzzzy
7482
/* 기타 */
wikitext
text/x-wiki
=코이코이=
코이코이는 일본에서 가장 많이 하는 화투 게임 중 하나입니다. 화투는 한 해의 12개월에 따라 자연을 묘사한 일본의 전통 카드 묶음입니다.
자기 손이나 카드 더미에서 바닥에 깔린 패와 같은 달의 패를 내야 패를 가져와 (특정 조합을 구성해 점수를 내는 족보인) 역을 만들 수 있습니다.
역을 만들면 멈추고 그 시점의 점수를 획득하거나, '코이코이'를 선언하고 계속 진행해 보다 강력한 역의 완성을 시도할 수 있습니다.
=게임방법=
2명의 플레이어는 각각 50 일본엽전을 가지고 시작합니다.
2명의 플레이어는 각각 8장의 패를 들고 바닥에도 8장의 패를 깔고 시작합니다.
2명의 플레이어는 각각 한턴씩 진행하는 방식입니다.
각각의 턴에서 패에서 한장을 바닥에 내려놓고 패 뭉치에서 한장 집어서 바닥에 내려놓습니다.
내려놓는 카드와 바닥에 있는 카드가 같은 달의 패면 가져올 수 있습니다.
바닥에 두장의 같은 달의 패가 있을 때는 둘 중 하나만 가져옵니다.
바닥에 세장의 같은 달의 패가 있을 때는 모든 카드를 가져옵니다.
가져온 카드의 조합, 즉 역에 따라 문(점수)을 획득할 수 있습니다.
=역의 종류=
게임중 아이콘을 누르면 역의 종류와 해당 역의 문을 볼 수 있는 리스트가 나오며, 리스트의 최하단에 12개월의 패를 알수 있습니다.
=기타=
1. 2명의 플레이어는 각각 50 일본엽전을 가지고 시작합니다.
2. 한 판의 게임은 6달(라운드) 또는 12달로 이루어져 있습니다.
3. 자신의 턴이 끝났을 때 문을 추가하는데 성공하면 코이코이나 쇼부를 선택할 수 있습니다.
쇼부를 선택하면 그 즉시 달의 진행이 끝나며 자신의 문만큼 상대의 일본 엽전을 가져올 수 있습니다.
코이코이를 선택하면 해당 달의 진행을 속행하며 다음 문 추가 때 코이코이선택 또는 쇼부를 선택할 수 있습니다.
4. 상대의 코이코이 이후 자신이 쇼부를 내어 달의 진행을 마무리할 경우 문이 두배가 되는데 이를 코이코이가에시(こいこい返し)라고 한다.
5. 쇼부를 내었을 때 7문이 넘으면 점수가 두배가 되는데 이를 바이츠케(倍付け)라고 한다.
6. 쇼부가 나지 않고 모든 플레이어가 패플 다 사용하면 먼저 시작한 플레이어가 승리하며 6문을 가져가느데 이를 친권이라고 한다.
7. 자신의 일본엽전을 모두 잃거나 게임이 종료했을 때 상대보다 일본엽전이 적으면 진다.
e01b08292c70ff409b826d7a39e5aa59b4c17320
대문
0
175
1276
1230
2021-09-17T10:57:10Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
</td>
<td valign="top">
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
0b6a4ad4e03bed8e8bcea1374ec10b98751c4527
1278
1276
2021-09-18T14:05:45Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''Available on BGA'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpelfenland|Elfenland]]
</td>
<td valign="top">
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelphearts|Hearts]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
a43a08fcee046e8257dc73bb656f74c008f93aa8
1281
1278
2021-09-19T07:25:35Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''BGA에서 플레이 가능한 게임'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
</td>
<td valign="top">
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
cf6f24f7698109ba50f83b52d91bd346417e503f
1282
1281
2021-09-19T07:25:59Z
Nilzzzzy
7482
/* Games */
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''BGA에서 플레이 가능한 게임'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
</td>
<td valign="top">
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
ce1715ffdf9dc65c7afc3338f21fad1c11294d55
1283
1282
2021-09-19T07:26:16Z
Nilzzzzy
7482
/* Games */
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''BGA에서 플레이 가능'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
</td>
<td valign="top">
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
b177d33adb2a660afa7ce58ed31121aa85008105
1284
1283
2021-09-19T07:26:30Z
Nilzzzzy
7482
/* Games */
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
</td>
<td valign="top">
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''Removed from BGA'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
f456c8a53e8919c8761719b23c2d6bd6375055a8
1285
1284
2021-09-19T07:28:00Z
Nilzzzzy
7482
/* Games */
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
</td>
<td valign="top">
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
</td>
<td valign="top">
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
</td>
<td valign="top">
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
1402e98ec6159786d7e83b5aa78d0c6c082f88fe
1287
1285
2021-09-19T09:36:53Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
</td>
<td valign="top">
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelplama|라마]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
</td>
<td valign="top">
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
</td>
<td valign="top">
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
a53b02d0b2b96bdb2127998eec4ce9b451f62e05
1289
1287
2021-09-19T09:59:31Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
</td>
<td valign="top">
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
</td>
<td valign="top">
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
</td>
<td valign="top">
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
* [[Gamehelpyatzy|Yahtzee]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
c4a02bba08c6a35c72e7c64121c00c009a4b3ec6
1290
1289
2021-09-19T10:15:55Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
</td>
<td valign="top">
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
</td>
<td valign="top">
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
</td>
<td valign="top">
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
6c9207f0c47c3939eaec2c28674dcaab60968dca
1291
1290
2021-09-19T10:17:53Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
</td>
<td valign="top">
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgomoku|Gomoku]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
</td>
<td valign="top">
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
</td>
<td valign="top">
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
05891c623139efb4e4a1607d34d83ed40adab1cf
1293
1291
2021-09-19T10:30:34Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
</td>
<td valign="top">
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
</td>
<td valign="top">
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
</td>
<td valign="top">
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
aa1a9d304536c1cc2e9c1d90018534281978744b
1294
1293
2021-09-19T10:31:26Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
</td>
<td valign="top">
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
* [[Gamehelplibertalia|Libertalia]]
</td>
<td valign="top">
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
</td>
<td valign="top">
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
ba7593e3074d49988a1758f5e5a72856997fd27d
1298
1294
2021-09-22T03:59:16Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpabandonallartichokes|아티초크 버리기]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
</td>
<td valign="top">
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
</td>
<td valign="top">
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
</td>
<td valign="top">
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
6e903a13ae766f714b32cc3ac69c8a4e3aa16987
Gamehelpsevenwonders
0
196
1277
2021-09-18T04:22:28Z
Nilzzzzy
7482
새 문서: ==7원더스==
wikitext
text/x-wiki
==7원더스==
31a4434a0dcb59a17531d0e4d0dce2f5246b73ff
Gamehelphearts
0
52
1280
830
2021-09-19T07:22:14Z
Nilzzzzy
7482
wikitext
text/x-wiki
하트는 4명의 플레이어가 진행하는 카드게임입니다.
하트에 사용되는 카드는 스페이드, 클로버, 하트, 다이아몬드 모양 2 ~ 10, A, J, Q, K입니다.
==규칙==
카드 크기는 2, 3, 4, 5, 6, 7, 8, 9, 10 ,J ,Q ,K ,A 순입니다.
목표는 100점(빠른 게임 적용시 75점)을 먼저 잃는 플레이어가 생기면 경기가 종료되고, 점수가 가장 높은 플레이어가 승리합니다.
각 라운드 종료시 얻은 카드 중 하트는 장당 1점, 스페이드 퀸은 장당 13점을 잃게됩니다.
'''슛 더 문(Shoot the moon)'''라운드 종료시 하트 13장, 스페이드 퀸을 얻으면 자신을 제외한 모든 플레이어가 26점을 잃게됩니다.
==준비 단계==
4명의 플레이어는 각각 13장의 카드를 나눠받습니다. 나눠받은 카드를 보고 3장의 카드를 1라운드에는 좌측, 2라운드에는 반대편, 3라운드에는 우측에게 넘겨주고, 4라운드에는 넘겨주지 않습니다.
4라운드 이후 게임이 종료되지 않으면 다시 1라운드부터 시작합니다.
==진행==
===게임의 시작===
클로버 2를 가진 사람이 가장 먼저 카드를 냅니다.
시계방향으로 돌면서 바닥에 깔린 카드와 같은 무늬의 카드를 냅니다.
같은무늬가 없다면 다른 무늬의 카드를 낼 수 있습니다.
단, 첫턴에는 하트와 스페이드 퀸을 낼 수 없습니다. (가지고 있는 카드가 모두 하트 또는 스페이드 퀸으로 이루어져있다면 낼 수 있습니다.)
===게임의 진행===
모든 사람이 카드를 바닥에 내려 놓으면 가장 먼저 내려놓은 카드와 같은 무늬의 카드 중 가장 높은 카드를 낸 사람이 내려놓은 카드를 모두 가져갑니다.
그 이후 카드를 가져간 사람이 원하는 카드를 낼 수 있습니다.
===하트 깨기===
같은 무늬가 없어 누군가 하트를 내게 된 것을 하트가 깨졌다고 하고 이 때부터 하트를 낼 수 있습니다.
0989a2d8651570c86835cb95fca0c04a6b018daf
1286
1280
2021-09-19T07:32:53Z
Nilzzzzy
7482
wikitext
text/x-wiki
==하트==
하트는 4명의 플레이어가 진행하는 카드게임입니다.
하트에 사용되는 카드는 스페이드, 클로버, 하트, 다이아몬드 모양 2 ~ 10, A, J, Q, K입니다.
==규칙==
카드 크기는 2, 3, 4, 5, 6, 7, 8, 9, 10 ,J ,Q ,K ,A 순입니다.
목표는 100점(빠른 게임 적용시 75점)을 먼저 잃는 플레이어가 생기면 경기가 종료되고, 점수가 가장 높은 플레이어가 승리합니다.
각 라운드 종료시 얻은 카드 중 하트는 장당 1점, 스페이드 퀸은 장당 13점을 잃게됩니다.
'''슛 더 문(Shoot the moon)'''라운드 종료시 하트 13장, 스페이드 퀸을 얻으면 자신을 제외한 모든 플레이어가 26점을 잃게됩니다.
==준비 단계==
4명의 플레이어는 각각 13장의 카드를 나눠받습니다. 나눠받은 카드를 보고 3장의 카드를 1라운드에는 좌측, 2라운드에는 반대편, 3라운드에는 우측에게 넘겨주고, 4라운드에는 넘겨주지 않습니다.
4라운드 이후 게임이 종료되지 않으면 다시 1라운드부터 시작합니다.
==진행==
===게임의 시작===
클로버 2를 가진 사람이 가장 먼저 카드를 냅니다.
시계방향으로 돌면서 바닥에 깔린 카드와 같은 무늬의 카드를 냅니다.
같은무늬가 없다면 다른 무늬의 카드를 낼 수 있습니다.
단, 첫턴에는 하트와 스페이드 퀸을 낼 수 없습니다. (가지고 있는 카드가 모두 하트 또는 스페이드 퀸으로 이루어져있다면 낼 수 있습니다.)
===게임의 진행===
모든 사람이 카드를 바닥에 내려 놓으면 가장 먼저 내려놓은 카드와 같은 무늬의 카드 중 가장 높은 카드를 낸 사람이 내려놓은 카드를 모두 가져갑니다.
그 이후 카드를 가져간 사람이 원하는 카드를 낼 수 있습니다.
===하트 깨기===
같은 무늬가 없어 누군가 하트를 내게 된 것을 하트가 깨졌다고 하고 이 때부터 하트를 낼 수 있습니다.
8201a1bf6ed208391d6d05518c41aaa71b1cc88f
Gamehelplama
0
197
1288
2021-09-19T09:58:56Z
Nilzzzzy
7482
새 문서: ==라마== 카드를 적게 들고 있을수록 좋지만, 라마를 남기지는 마세요. ==승리조건== 게임은 어느 한 플레이어가 -40점에 도달하면 종료됩니...
wikitext
text/x-wiki
==라마==
카드를 적게 들고 있을수록 좋지만, 라마를 남기지는 마세요.
==승리조건==
게임은 어느 한 플레이어가 -40점에 도달하면 종료됩니다.
이 때, 점수가 가장 높은 사람이 승리하게됩니다.
==게임 방법==
라마는 4명의 플레이어가 하는 카드게임입니다. 1~6,라마를 각각 8장씩 총 56장의 카드를 사용합니다.
카드의 크기는 라마, 1, 2, 3, 4, 5, 6, 라마입니다.
===라운드 시작===
모든 플레이어는 6장의 카드를 받고 카드뭉치에서 한장을 뒤집어 바닥에 놓습니다.
===라운드 진행===
자신의 차례가 되면 카드를 1장 내거나 1장 받거나 라운드에 빠지는 것 중 한가지 행동을 해야합니다.
1. 카드를 내려면 바닥의 카드와 같은 카드거나 크기가 1 더 높은 카드여야 합니다.
2. 카드뭉치에 카드가 없으면 카드를 받을 수 없습니다.
3. 라운드에서 빠지면 해당 플레이어의 차례는 라운드가 끝날 때까지 건너뜁니다.
4. 1명을 제외한 모든 플레이어가 라운드에서 빠지면 더 이상 카드를 뽑을 수 없습니다.
5. 1명을 제외한 모든 플레이어가 라운드에서 빠지면 남은 한사람이 연속으로 차례를 진행합니다.
6. 1명을 제외한 모든 플레이어가 라운드에서 빠졌을 때 모든 카드를 연속해서 낼 수 있는 상황이 되면 모든 카드를 내려놓는 동작이 활성화됩니다.
===라운드 종료===
모든 플레이어가 라운드에서 빠지거나 한명의 플레이어가 0장의 카드를 갖고 있을 경우 라운드가 종료됩니다.
라운드 종료 후 점수계산이 이뤄집니다.
===점수 계산===
1. 숫자 카드를 가지고 있으면 해당 숫자만큼 감점이 됩니다. 이 때, 같은 숫자카드를 몇 장을 가지고 있든 한번만 감점됩니다.
2. 라마 카드를 가지고 있으면 10점이 감점됩니다. 이 때, 라마 카드를 몇 장을 가지고 있든 한번만 감점됩니다.
3. 라운드 종료시 0장의 카드를 가지고 있으면 점수를 얻습니다.
자신의 점수가 -10점 이하면 10점을 얻습니다.
자신의 점수가 -1 ~ -9점이면 1점을 얻습니다.
자신의 점수가 0점 이상이면 0점을 얻습니다.
552cd622be8f8c0a7cca1d4414263e660f98ced7
Gamehelpgomoku
0
81
1292
422
2021-09-19T10:29:55Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요==
오목은 흑,백 두명의 플레이어가 번갈아 한 수씩 두어 가로, 세로, 대각선 중 한 방향으로 같은 색 돌을 5개를 먼저 놓으면 승리하는 게임입니다.
==게임 진행==
흑이 선수를 둡니다. 흑의 두번째 수는 첫 돌이 놓아진 곳에서 가로나 세로에서 3칸 옆에 두어야합니다.
==금수==
수학적으로 흑이 항상 최선의 자리에 둘 경우 언제나 이기게 됨이 수학적으로 증명됨에 따라 흑에 걸린 제약이다.
1. 흑은 3*3, 4*3, 4*4등을 둘 수 없다. (닫힌 3*3, 4*3 등이면 둘 수 있다.)
2. 6목이상시 승리조건이 아님
54c3a9fd48ccecf5ea56676af80aafe3258df381
1295
1292
2021-09-20T01:49:33Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요==
오목은 흑,백 두명의 플레이어가 번갈아 한 수씩 두어 가로, 세로, 대각선 중 한 방향으로 같은 색 돌을 5개를 먼저 놓으면 승리하는 게임입니다. 단 흑은 6목 이상이 안됩니다.
==게임 진행==
흑이 선수를 둡니다. 흑의 두번째 수는 첫 돌이 놓아진 곳에서 가로나 세로에서 3칸 옆에 두어야합니다.
f72bd01c723248a406b68df2762b14775c4e6c5d
1296
1295
2021-09-21T03:34:04Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요==
오목은 흑,백 두명의 플레이어가 번갈아 한 수씩 두어 가로, 세로, 대각선 중 한 방향으로 같은 색 돌을 5개를 먼저 놓으면 승리하는 게임입니다. 흑, 백 둘다 6목이상 안됩니다.
==게임 진행==
흑이 선수를 둡니다. 흑의 두번째 수는 첫 돌이 놓아진 곳에서 가로나 세로에서 3칸 옆에 두어야합니다.
2cad4e14799f58afd4cdcf21b907eb915dc4e813
Gamehelpabandonallartichokes
0
198
1297
2021-09-22T03:55:44Z
Nilzzzzy
7482
새 문서: ==아티초크 버리기== 매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다. ==게임 진행== 2명의 플레이어가 번갈가며 진행을...
wikitext
text/x-wiki
==아티초크 버리기==
매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다.
==게임 진행==
2명의 플레이어가 번갈가며 진행을 합니다.
자신의 턴이 시작되면 채소 하나를 수확하고, 손에 있는 채소를 사용할 수 있습니다.
차례를 마치면 손의 카드를 버린 뒤 카드를 5장 뽑습니다. 카드를 뽑을 때 카드더미에 카드가 부족하면 버린 카드 더미의 카드를 모두 카드 더미에 넣고 섞습니다. 이후, 부족한만큼 더 뽑습니다.
이 때, 아티초크가 없다면 게임에서 승리합니다.
==카드 설명==
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===감자(POTATO)===
내 카드 더미 맨 위의 카드를 공개하여 아티초크면 묻고 아니면 버립니다.
===브로콜리===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 내 카드 더미 맨 위에 올립니다.
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 모든 플레이어는 각자 왼쪽으로 카드 2장을 넘깁니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 1장은 내 버린 카드 더미에, 다른 1장은 상대 1명의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORNS)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다.
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
좋아!
줄기가 가려워!
42d114a836482ddfa5b8ae436a2af755b2f3c9a6
1299
1297
2021-09-22T04:00:10Z
Nilzzzzy
7482
/* 아티초크(ARTICHOKE) */
wikitext
text/x-wiki
==아티초크 버리기==
매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다.
==게임 진행==
2명의 플레이어가 번갈가며 진행을 합니다.
자신의 턴이 시작되면 채소 하나를 수확하고, 손에 있는 채소를 사용할 수 있습니다.
차례를 마치면 손의 카드를 버린 뒤 카드를 5장 뽑습니다. 카드를 뽑을 때 카드더미에 카드가 부족하면 버린 카드 더미의 카드를 모두 카드 더미에 넣고 섞습니다. 이후, 부족한만큼 더 뽑습니다.
이 때, 아티초크가 없다면 게임에서 승리합니다.
==카드 설명==
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===감자(POTATO)===
내 카드 더미 맨 위의 카드를 공개하여 아티초크면 묻고 아니면 버립니다.
===브로콜리===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 내 카드 더미 맨 위에 올립니다.
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 모든 플레이어는 각자 왼쪽으로 카드 2장을 넘깁니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 1장은 내 버린 카드 더미에, 다른 1장은 상대 1명의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORNS)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다. 이 카드는 게임이 시작될 때 내 카드 더미에 10장씩 있습니다.
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
좋아!
줄기가 가려워!
475857574c06264711d6b0a168c0e67fa2ef82cb
1300
1299
2021-09-22T04:00:28Z
Nilzzzzy
7482
/* 게임 진행 */
wikitext
text/x-wiki
==아티초크 버리기==
매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다.
==게임 진행==
2명의 플레이어가 번갈가며 진행을 합니다.
자신의 턴이 시작되면 채소 하나를 수확하고, 손에 있는 채소를 사용할 수 있습니다.
차례를 마치면 손의 카드를 버린 뒤 카드를 5장 뽑습니다. 카드를 뽑을 때 카드 더미에 카드가 부족하면 버린 카드 더미의 카드를 모두 카드 더미에 넣고 섞습니다. 이후, 부족한만큼 더 뽑습니다.
이 때, 아티초크가 없다면 게임에서 승리합니다.
==카드 설명==
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===감자(POTATO)===
내 카드 더미 맨 위의 카드를 공개하여 아티초크면 묻고 아니면 버립니다.
===브로콜리===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 내 카드 더미 맨 위에 올립니다.
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 모든 플레이어는 각자 왼쪽으로 카드 2장을 넘깁니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 1장은 내 버린 카드 더미에, 다른 1장은 상대 1명의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORNS)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다. 이 카드는 게임이 시작될 때 내 카드 더미에 10장씩 있습니다.
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
좋아!
줄기가 가려워!
4e00e13f4dfa36e0f69d86e57f3e92fdc581bb0c
1301
1300
2021-09-22T04:17:52Z
Nilzzzzy
7482
/* 아티초크(ARTICHOKE) */
wikitext
text/x-wiki
==아티초크 버리기==
매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다.
==게임 진행==
2명의 플레이어가 번갈가며 진행을 합니다.
자신의 턴이 시작되면 채소 하나를 수확하고, 손에 있는 채소를 사용할 수 있습니다.
차례를 마치면 손의 카드를 버린 뒤 카드를 5장 뽑습니다. 카드를 뽑을 때 카드 더미에 카드가 부족하면 버린 카드 더미의 카드를 모두 카드 더미에 넣고 섞습니다. 이후, 부족한만큼 더 뽑습니다.
이 때, 아티초크가 없다면 게임에서 승리합니다.
==카드 설명==
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===감자(POTATO)===
내 카드 더미 맨 위의 카드를 공개하여 아티초크면 묻고 아니면 버립니다.
===브로콜리===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 내 카드 더미 맨 위에 올립니다.
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 모든 플레이어는 각자 왼쪽으로 카드 2장을 넘깁니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 1장은 내 버린 카드 더미에, 다른 1장은 상대 1명의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORNS)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다. 이 카드는 게임이 시작될 때 내 카드 더미에 10장씩 있습니다.
좋아!
줄기가 가려워!
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
b19d751a2957c75ffa4cf4573bc42f57cbfbe669
Gamehelpabandonallartichokes
0
198
1302
1301
2021-09-22T04:44:15Z
Nilzzzzy
7482
/* 카드 설명 */
wikitext
text/x-wiki
==아티초크 버리기==
매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다.
==게임 진행==
2명의 플레이어가 번갈가며 진행을 합니다.
자신의 턴이 시작되면 채소 하나를 수확하고, 손에 있는 채소를 사용할 수 있습니다.
차례를 마치면 손의 카드를 버린 뒤 카드를 5장 뽑습니다. 카드를 뽑을 때 카드 더미에 카드가 부족하면 버린 카드 더미의 카드를 모두 카드 더미에 넣고 섞습니다. 이후, 부족한만큼 더 뽑습니다.
이 때, 아티초크가 없다면 게임에서 승리합니다.
==카드 설명==
===리크(LEEK)===
상대 1명을 골라 카드 더미 맨 위의 카드를 공개하여 내 손으로 가져오거나 그 상대의 버린 카드 더미에 놓습니다.
===비트(BEET)===
상대 1명을 지정하고, 각자의 손에서 무작위로 카드를 골라 공개합니다. 나와 상대의 카드가 둘 다 아티초크라면 두 카드를 모두 묻고, 아니면 서로 맞바꿉니다.
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===감자(POTATO)===
내 카드 더미 맨 위의 카드를 공개하여 아티초크면 묻고 아니면 버립니다.
===브로콜리===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 내 카드 더미 맨 위에 올립니다.
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 모든 플레이어는 각자 왼쪽으로 카드 2장을 넘깁니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 1장은 내 버린 카드 더미에, 다른 1장은 상대 1명의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORN)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다. 이 카드는 게임이 시작될 때 내 카드 더미에 10장씩 있습니다.
좋아!
줄기가 가려워!
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
77e8d25c05a23a435104184a48155917b9e4dc02
1303
1302
2021-09-22T04:52:22Z
Nilzzzzy
7482
wikitext
text/x-wiki
==아티초크 버리기==
매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다.
==게임 진행==
2명의 플레이어가 번갈가며 진행을 합니다.
자신의 턴이 시작되면 채소 하나를 수확하고, 손에 있는 채소를 사용할 수 있습니다.
차례를 마치면 손의 카드를 버린 뒤 카드를 5장 뽑습니다. 카드를 뽑을 때 카드 더미에 카드가 부족하면 버린 카드 더미의 카드를 모두 카드 더미에 넣고 섞습니다. 이후, 부족한만큼 더 뽑습니다.
이 때, 아티초크가 없다면 게임에서 승리합니다.
==카드 설명==
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 모든 플레이어는 각자 왼쪽으로 카드 2장을 넘깁니다.
===감자(POTATO)===
내 카드 더미 맨 위의 카드를 공개하여 아티초크면 묻고 아니면 버립니다.
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===리크(LEEK)===
상대 1명을 골라 카드 더미 맨 위의 카드를 공개하여 내 손으로 가져오거나 그 상대의 버린 카드 더미에 놓습니다.
===브로콜리(BROCCOLI)===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===비트(BEET)===
상대 1명을 지정하고, 각자의 손에서 무작위로 카드를 골라 공개합니다. 나와 상대의 카드가 둘 다 아티초크라면 두 카드를 모두 묻고, 아니면 서로 맞바꿉니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 1장은 내 버린 카드 더미에, 다른 1장은 상대 1명의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORN)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 내 카드 더미 맨 위에 올립니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다. 이 카드는 게임이 시작될 때 내 카드 더미에 10장씩 있습니다.
좋아!
줄기가 가려워!
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
89090a8da882e0c9dbd9ad1d68cedcc368527115
1307
1303
2021-10-06T04:30:22Z
Nilzzzzy
7482
wikitext
text/x-wiki
==아티초크 버리기==
매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다.
==게임 진행==
2명의 플레이어가 번갈가며 진행을 합니다.
자신의 턴이 시작되면 채소 하나를 수확하고, 손에 있는 채소를 사용할 수 있습니다.
차례를 마치면 손의 카드를 버린 뒤 카드를 5장 뽑습니다. 카드를 뽑을 때 카드 더미에 카드가 부족하면 버린 카드 더미의 카드를 모두 카드 더미에 넣고 섞습니다. 이후, 부족한만큼 더 뽑습니다.
이 때, 아티초크가 없다면 게임에서 승리합니다.
==카드 설명==
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 모든 플레이어는 각자 왼쪽으로 카드 2장을 넘깁니다.
===감자(POTATO)===
내 카드 더미 맨 위의 카드를 공개하여 아티초크면 묻고 아니면 버립니다.
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===리크(LEEK)===
상대 1명을 골라 카드 더미 맨 위의 카드를 공개하여 내 손으로 가져오거나 그 상대의 버린 카드 더미에 놓습니다.
===브로콜리(BROCCOLI)===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===비트(BEET)===
상대 1명을 지정하고, 각자의 손에서 무작위로 카드를 골라 공개합니다. 나와 상대의 카드가 둘 다 아티초크라면 두 카드를 모두 묻고, 아니면 서로 맞바꿉니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 1장은 내 버린 카드 더미에, 다른 1장은 상대 1명의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORN)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 내 카드 더미 맨 위에 올립니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다. 이 카드는 게임이 시작될 때 내 카드 더미에 10장씩 있습니다.
좋아!
줄기가 가려워!
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
===루바브(RHUPARB)===
이 카드를 묻고 정원의 카드를 모두 교체한 뒤 카드 1장을 수확합니다.(정원에 있던 카드는 정원 카드 더미 밑으로 되돌립니다.)
c45f3b339116b29da6225865e4d73189ff71a312
1308
1307
2021-10-06T05:23:20Z
Nilzzzzy
7482
/* 루바브(RHUPARB) */
wikitext
text/x-wiki
==아티초크 버리기==
매력적인 채소로 가득한 이 게임에서는 아티초크를 버려야 합니다.
==게임 진행==
2명의 플레이어가 번갈가며 진행을 합니다.
자신의 턴이 시작되면 채소 하나를 수확하고, 손에 있는 채소를 사용할 수 있습니다.
차례를 마치면 손의 카드를 버린 뒤 카드를 5장 뽑습니다. 카드를 뽑을 때 카드 더미에 카드가 부족하면 버린 카드 더미의 카드를 모두 카드 더미에 넣고 섞습니다. 이후, 부족한만큼 더 뽑습니다.
이 때, 아티초크가 없다면 게임에서 승리합니다.
==카드 설명==
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 모든 플레이어는 각자 왼쪽으로 카드 2장을 넘깁니다.
===감자(POTATO)===
내 카드 더미 맨 위의 카드를 공개하여 아티초크면 묻고 아니면 버립니다.
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===리크(LEEK)===
상대 1명을 골라 카드 더미 맨 위의 카드를 공개하여 내 손으로 가져오거나 그 상대의 버린 카드 더미에 놓습니다.
===브로콜리(BROCCOLI)===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===비트(BEET)===
상대 1명을 지정하고, 각자의 손에서 무작위로 카드를 골라 공개합니다. 나와 상대의 카드가 둘 다 아티초크라면 두 카드를 모두 묻고, 아니면 서로 맞바꿉니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 1장은 내 버린 카드 더미에, 다른 1장은 상대 1명의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORN)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 내 카드 더미 맨 위에 올립니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다. 이 카드는 게임이 시작될 때 내 카드 더미에 10장씩 있습니다.
좋아!
줄기가 가려워!
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
===루바브(RHUBARB)===
이 카드를 묻고 정원의 카드를 모두 교체한 뒤 카드 1장을 수확합니다.(정원에 있던 카드는 정원 카드 더미 밑으로 되돌립니다.)
0fe214e12e2e031d7bf5e03b5eb33311111a80a6
Gamehelpbang
0
199
1304
2021-09-30T14:58:22Z
Opsty
7576
새 문서: 직업 보안관, 부관, 무법자, 배신자 4개의 직업이 있으며 보안관은 직업을 공개한 채로 시작합니다. 이때 플레이어의 수에 따라 4명 : 1보...
wikitext
text/x-wiki
직업
보안관, 부관, 무법자, 배신자 4개의 직업이 있으며 보안관은 직업을 공개한 채로 시작합니다. 이때 플레이어의 수에 따라
4명 : 1보안관, 2무법자, 1배신자
5명 : 1보안관, 2무법자, 1부관, 1배신자
6명 : 1보안관, 3무법자, 1부관, 1배신자
7명 : 1보안관, 3무법자, 2부관, 1배신자
로 게임이 진행됩니다.
승리조건
보안관, 부관 : 무법자와 배신자를 모두 처치하면 승리
무법자 : 보안관을 처치하면 승리
배신자 : 홀로 살아남으면 승리 (단, 무법자 혹은 부관이 생존했을때 보안관이 죽으면 무법자의 승리)
게임 시작
게임은 보안관부터 시작합니다.
자신의 차례가 시작될 때 카드를 2장 뽑습니다. 이후 카드를 원하는 만큼 사용합니다. (단, 뱅! 은 한 턴에 한번만 사용할 수 있습니다)
차례를 마칠 때, 자신의 생명력 만큼 카드를 들고 있을 수 있으며 이외의 카드들은 버려야 합니다.
9831c8c3660f7ff47a04f554743e8b972bd717b4
Tips abandonallartichokes
0
200
1305
2021-10-05T04:08:34Z
Pleasebelieveme
7586
새 문서: Abandon All Artichokes에는 2가지 광범위한 전략이 있습니다. 덱에서 모든 아티초크를 제거하거나, 아티초크가 없는 핸드를 뽑을 가능성이 높은...
wikitext
text/x-wiki
Abandon All Artichokes에는 2가지 광범위한 전략이 있습니다. 덱에서 모든 아티초크를 제거하거나, 아티초크가 없는 핸드를 뽑을 가능성이 높은 큰 덱을 사용합니다.
좋은 초기 게임 카드:
당근 - 사용할 다른 카드가 없기 때문에 기회 비용 없이 2개의 아티초크를 퇴비화합니다.
감자 - 첫 번째 라운드에서 퇴비화할 아티초크를 찾을 가능성이 높습니다.
브로콜리 - 적어도 3개의 아티초크를 손에 들고 있을 가능성이 있습니다.
가지 - 퇴비 아티초크, 통과해도 효과가 없을 것
비트 - 손에 있는 무작위 카드는 거래되거나 퇴비화되는 아티초크임이 거의 확실합니다.
좋은 늦은 게임 카드:
부추 - 상대방에게서 아티초크가 아닌 것을 훔칩니다.
가지 - 손에 아티초크가 3개 이상 있으면 하나는 퇴비로 만들고 나머지 두 개는 통과시킬 수 있습니다. 운이 좋다면 손에 아티초크가 없을 수도 있습니다.
후추 - 덱을 쌓아 아티초크가 아닌 것을 더 많이 그릴 수 있습니다. 감자가 퇴비로 만들 수 있도록 아티초크를 넣을 수도 있습니다.
비트 - 손에 아티초크만 남아 있을 때 비트를 재생하여 아티초크가 거래/퇴비를 위해 무작위로 선택되도록 합니다. 상대방에게서 뭔가 유용한 걸 얻을 수 있을지도 몰라요!
좋은 아티초크 없는 전략 카드:
당근 - 퇴비 2 아티초크
양파 - 아티초크 퇴비
가지 - 아티초크 퇴비
좋은 빅덱 전략 카드:
옥수수 - 덱에 추가 카드를 넣습니다. 단점: 아티초크를 잡고 놀아야 함
완두콩 - 추가 카드를 덱에 추가: 단점: 상대에게 제공
후추 - 덱을 쌓아서 아티초크가 아닌 것을 더 많이 그릴 수 있습니다.
359b0b289ee58f00e1794096af77cd5faa075113
Tips hearts
0
201
1306
2021-10-05T09:11:28Z
Pleasebelieveme
7586
새 문서: 달 촬영(26점 모두 획득): 카드가 있는 경우에만 달을 쏘려고 합니다. 높은 카드를 갖는 것이 도움이 되지만, 그것보다 더 많은 것이 있습...
wikitext
text/x-wiki
달 촬영(26점 모두 획득):
카드가 있는 경우에만 달을 쏘려고 합니다. 높은 카드를 갖는 것이 도움이 되지만, 그것보다 더 많은 것이 있습니다. 첫째, 한 벌을 많이 갖는 것이 좋습니다. 왜냐하면 그 소송의 몇 라운드가 인도되고 나면 다른 사람들이 모두 소진되고 아무도 당신에게서 주도권을 빼앗지 않고 그 소송으로 인도할 수 있기 때문입니다. 비록 낮은 카드일지라도. 실패하더라도 아무도 그 소송을 이끌지 않을 것이기 때문에 너무 많은 카드를 가져갈까 걱정할 필요가 없기 때문에 이것은 또한 좋습니다.
마음이 낮고 달을 쏘고 싶다면 교환하십시오. 거래 세션이 끝나면 누군가가 당신보다 높은 마음을 가지고 있다면 달을 쏘려고하지 마십시오. 유일한 예외는 다른 사람보다 높은 마음을 충분히 가지고 있어서 낮은 마음을 연주하기 전에 모두가 고갈될 가능성이 있다는 것입니다.
다른 사람들이 달을 쏘는 것을 막는 것:
달을 쏘려고 하는 사람들을 조심하세요. 대부분의 경우 이러한 상황은 손 시작 시 왼쪽으로 전달하는 세 장의 카드 중 하나가 손에 들고 있는 카드보다 심장이 낮은 카드인지 확인함으로써 피할 수 있습니다. 이런 식으로 하트 트릭을 하고 4점만 얻으면 항상 달을 멈출 수 있습니다. 특정 수트가 4~5개 이상 있는 경우 자신이 점수를 얻거나 다른 두 명 이상의 플레이어가 점수를 받을 때까지 가장 높은 수트를 플레이할 때까지 기다리십시오. 점수를 얻지 않고 해당 슈트를 플레이할 수 있다면 두 번째로 높은 슈트를 플레이하십시오. 그렇게하면 자신을 나쁜 상황에 빠뜨리지 않고 가장 높은 카드로 달을 막을 수 있습니다.
첫 번째 트릭:
여기에는 많은 옵션이 없습니다. Two of Clubs가 있다면 당신이 그것을 이끌고 있는 것입니다. 첫 번째 트릭에서는 점수가 떨어질 수 없으므로 가장 높은 클럽에서 플레이하십시오. 클럽에서 무효인 경우 다른 위험한 하이 카드(예: Ace 또는 King of Spades)를 폐기하거나 두 번째 소송에서 자신을 무효화할 기회를 사용하십시오. 더 많은 공백은 나중에 더 많은 기회를 의미합니다.
블리딩 스페이드:
일반적으로 말해서 첫 번째 트릭이 실패한 후 스페이드의 여왕을 차지할 위험이 없는 플레이어는 가능한 한 스페이드를 앞서고 싶어할 것입니다. 이 이면의 주요 이론은 간단합니다. 스페이드가 계속 리드되면 A, K 및 Q를 가진 플레이어가 결국에는 스페이드를 플레이해야 합니다. 만약 당신이 그 카드들을 가지고 있지 않다면, 당신은 그것들을 가능한 한 빨리 플레이하도록 하고 싶어, 그래서 다른 누군가는 그 13포인트에 갇히게 될 것입니다. 스페이드 출혈에 실패하면 퀸을 들고 있는 플레이어가 다른 슈트(예: 클럽 또는 다이아몬드)에 빈 공간을 만든 다음 퀸을 오프 슈트 트릭으로 버릴 수 있습니다. 트릭을 이길 가능성이 높은 카드가 없는 거의 완벽한 핸드를 들고 있지 않는 한, 여왕이 다른 사람에게 떨어질 때까지 전투 계획에는 가능한 한 많은 스페이드를 이끄는 것이 포함되어야 합니다.
블리딩 스페이드의 예외:
여기에는 예외가 있습니다. 13점 이하의 다른 플레이어가 있고 게임을 끝내고 싶지 않다면 그가 가지고 있으면 강제로 게임을 하고 싶지 않으므로 먼저 누가 그것을 가지고 있는지 알아내십시오. 이기고 있는 플레이어가 그것을 가지고 있다면, 반드시 출혈을 일으키고, 지는 플레이어가 그것을 가지고 있다면, 그가 준비가 되었을 때 플레이할 수 있도록 먼저 보이드를 가져오도록 하십시오. 그는 아마도 이기고 있는 플레이어에게 게임을 시도할 것입니다. 누가 가지고 있는지 알 수 없더라도 리드를 가진 플레이어가 아닐 확률이 3분의 2이기 때문에 스페이드를 흘리지 않는 것이 좋습니다. 리드와 함께 플레이어에게 여왕. 누가 스페이드의 여왕을 가지고 있는지 알아내는 몇 가지 방법이 있습니다. 첫째, 스페이드가 이끄는 라운드에서 스페이드가 아닌 플레이를 하는 사람을 확실히 제거할 수 있습니다. 여왕이 있으면 하지 않을 것이기 때문에 삽으로 리드하는 사람을 제거할 수도 있습니다. 마지막으로, 누군가가 높은 클럽이나 다이아몬드로 선두를 달리고 있고 그 슈트를 이미 한 두 번 이상 연주했다면 아마도 여왕이 있거나 달을 쏘려고 한다는 의미일 것입니다. 위험한 움직임.
방어 스페이드:
반대로, 방어되지 않은 Q, K 또는 A 스페이드에 갇힌 경우 스페이드가 계속 이끌리면 퀸을 가져갈 위험이 있습니다. 당신의 목표는 카드가 한두 장 밖에 없는 수트를 이끌고 가능한 한 빨리 공백을 만드는 것이어야 합니다. 예를 들어, 다이아몬드 두 개만 버리면 다른 사람이 다이아몬드를 이끌고 당신이 나쁜 스페이드를 떨어뜨릴 수 있기를 바랄 수 있습니다. 퀸 오브 스페이드를 들고 있다면 더 긴 슈트(클럽 또는 다이아몬드)를 이끌고 다른 사람이 무효화되기를 바라는 또 다른 옵션이 있습니다. 당신이 스페이드의 여왕을 잡고 있기 때문에 일어날 최악의 상황은 몇 가지 심장 포인트가 당신에게 떨어질 것입니다. 이 일이 일어나면 마음이 부서지고 사람들이 삽 대신 마음을 이끌 수 있습니다. 하트가 적고 하트 트릭에 여왕을 버릴 수 있다면 이것이 이상적입니다.
하트:
나쁜 카드들입니다. 스페이드의 여왕을 피하고 나면 많은 것을 얻지 않으려고 합니다. 쉬워보이죠? 글쎄, 그것은 당신이 당신의 손에 어떤 카드를 가지고 있는지에 달려 있습니다. 마음이 낮으면 어떤 마음의 리드에도 굴복할 수 있으므로 걱정할 필요가 없습니다. 당신이 높은 마음을 잡고 있다면, 당신은 그것을 다른 사람에게 가능한 한 빨리 차고 싶어하고 마음을 이끌지 않습니다.
공허:
한 벌의 모든 카드를 제거하여 조기 공백을 만들 수 있다면 거의 항상 그렇게 해야 합니다. 이렇게 하면 다음에 해당 소송이 주도될 때 가장 강력한 위치인 최악의 카드를 제거할 수 있음을 의미합니다. 마찬가지로, 공석이 있는 테이블의 다른 플레이어를 추적하는 것이 중요하므로 얽매일 수 있는 소송을 진행하지 마십시오.
계산:
Hearts를 플레이하는 데 꼭 필요한 것은 아니지만 각 슈트가 몇 번이나 플레이되었는지 추적할 수 있다면 훨씬 더 잘할 수 있습니다. 이것은 들리는 것보다 덜 어렵습니다. 누군가가 오프 슈트 카드를 버려서 빈 공간을 드러낼 때까지 모든 슈트의 카드 수는 4로 나눌 수 있습니다. 이것은 다른 플레이어의 빈 공간으로 플레이하지 않도록 추적하는 중요한 정보입니다. 예를 들어, 3개의 전체 클럽 라운드를 플레이하고 손에 클럽이 있으면 그것이 마지막 라운드입니다. 그것을 주도하면 다른 모든 사람들이 당신에게 카드를 버릴 수 있습니다.
늦은 게임 전략:
스스로 포인트를 가져가는 위험을 감수하지 않고 포인트를 처리하는 대상을 항상 제어할 수는 없지만 가능하면 해야 합니다. 당신이 이기고 있다면, 게임이 더 빨리 끝날 수 있도록 지는 플레이어를 목표로 삼고 싶을 것입니다. 그렇지 않으면 이기고 있는 플레이어를 타겟팅하려고 합니다. 스페이드의 여왕이 있다면 목표로 하는 플레이어에게 주고 싶지만, 스스로 가져갈 위험 없이 그렇게 할 수 있는 경우에만 가능합니다. 스페이드가 많으면 대상에게 줄 수 있을 때까지 퀸에 매달릴 여유가 있지만, 그렇지 않은 경우 게임이 종료되지 않는 한 가능한 한 제거하십시오 . 마음의 경우도 마찬가지입니다.
일반적으로 게임이 후반부에 진행될수록 상대방이 달을 쏘는 것에 대해 덜 걱정해야 합니다. 몇 점만 남으면 게임에서 질 만큼 충분한 점수를 얻지 않고는 누구도 막을 수 없으므로 게임에서 지지 않고 그렇게 할 수 있는 다른 플레이어에게 맡기십시오. 당신이 선두에 있고, 당신이 그것을 쏘고 있는 플레이어보다 적어도 27점 앞서 있고, 26점 이하의 다른 플레이어가 적어도 한 명이 있다면, 당신은 다른 플레이어들이 슛을 하는 것을 멈추게 해서는 안 됩니다. 경우에는 승리하게 됩니다. 이기고 있는 플레이어가 달을 쏘려고 한다면, 그것이 당신의 유일한 희망일 수 있기 때문에 그를 막기 전에 가능한 한 멀리 가도록 하는 것이 좋습니다.
8bac5be00f7abe16137e8a04eca66ca2fae6d505
Tips bang
0
202
1309
2021-10-17T12:44:46Z
Yeongjun
7622
새 문서: == 보안관으로 플레이하는 법 == 무엇보다 부관을 빨리 찾아내야 되고 생명력 1이 늘어나기 때문에 잡화점에서 빗나감보다는 공격형 카드(...
wikitext
text/x-wiki
== 보안관으로 플레이하는 법 ==
무엇보다 부관을 빨리 찾아내야 되고 생명력 1이 늘어나기 때문에 잡화점에서 빗나감보다는 공격형 카드(인디언, 기관총, 결투 등)를 가져오는게 좋다. 맥주가 있다면 맥주를 가져오자.
4인이라면 배신자와 손잡고 무법자를 죽이되, 막타를 치도록 하자. 이때 들어오는 카드 3장이 의외로 크다. 그리고 남은 둘이서 개싸움을 할 동안 자신은 방어만 하면서 1 대 1 상황을 대비하자. 배신자는 무조건 무법자를 쏠 것이고, 무법자는 보안관을 쏘는 것 자체가 2 대 1 상황을 부르는 것이니 배신자를 쏠 것이다. 그 다음에 1 대 1 상황이 오면 살아남은 사람은 피가 2~3이거나 손패가 말라 있을 것이다. 이때 이기는 것은 식은 죽 먹기.
5인이면 부관이 있기 때문에 무법자 1명을 죽이고 각자 거리가 가까운 무법자 배신자 중 하나를 집중 공격하면 된다. 이때 서로 다른 사람을 공격하자.
6인이면 무법자가 3명이기에 매우 까다로워진다. 무법자 2명을 죽이고 5인 때와 똑같이 하면 된다. 무법자 죽이는 동안에 죽지 않기를 빈다....
7인이면 부관이 1명 더 늘어 더 수월해진다. 무법자 1명을 죽이고 5인 때처럼 하자.
8인이면 배신자가 늘어나 배신자가 부관부터 죽이면 곤란해진다. 배신자 1명, 무법자 1명을 죽이고 5인 때와 같이 하자.
== 부관으로 플레이하는 법 ==
5, 6인플에서는 자신과 보안관 빼고는 다 적이라고 생각하면 된다. 5인플에서는 무법자라 생각되는 사람을 치자. 다른 사람들에게는 적절한 정치질로 자신이 무법자를 치고 있다고 믿게 해야 한다.
이렇게 해서 무법자가 죽으면 보안-무법-배신-부관 상황이 되는데 이때는 배신자한테 죽지 않도록 조심해야 한다. 이렇게 버티면서 배신자나 무법자 하나가 죽으면 2대 1 상황이 되면서 게임 끝. 자신이 죽더라도 나를 죽인 사람은 보안관이 쉽게 죽인다. 이렇게 자신을 희생해서 보안관이 이기도록 해야 할 것이다.
== 무법자로 플레이하는 법 ==
보안관 카드 상황을 보고 생각하자.
1. 보안관이 가진 카드가 거의 없다.
무조건 보안관 명치를 친다. 이 행위를 무법자가 자기 정체를 드러낸다 하여 '무밍아웃'이라고 부른다. 무밍아웃 하는 순간 부관과 배신자가 견제하기 시작할 것인데, 이를 견디기 위한 방어 수단이 있으면 좋다.
2. 보안관 장비는 꽤 있는데 허리가 비었다.
우선 귀찮은 장비(술통, 야생마 등등)를 덜어낼 카드가 있는지 확인한다. 장비를 덜어낼 수 있다면, 장비를 덜어낸 다음 바로 공격하자. 장비를 덜어내지 못한다면, 차라리 부관으로 보이는 녀석을 무법이라 선동하면서 견제하자. 부관도 보안관에게 의심살 짓을 하는 놈이 꼭 하나씩은 있기 마련이다.
3. 보안관 장비는 부실한데 허리는 튼실하다.
광역기 돌리면서 허리부터 비운다. 보안관 핸드에 빗나감이 떨어졌다[31]고 생각되는 시점에서 무밍아웃 한다. 보안관은 엥간하면 광역기를 피하므로, 게틀링같은 빗나감 제출 광역기를 피하지 못한다면 높은 확률로 노빗이다.가끔 재수없으면 보안관 허리의 모든 카드가 빗나감일때도 있다(...)
4. 보안관 장비도 허리도 튼실하다.
보안관이 강캐를 잡고 카드 사기를 친 경우가 대부분이다. 안타깝지만, 이쯤되면 무법/배자가 이기기 정말 어려운 상태. 다만, 무법자들이 죽지 않은 상태에서 보안관을 도울 부관들을 다 떨어내면, 보안관은 오래 버티지 못한다. 고로 부관인 척 하며 부관들부터 쳐내자. 보안관이 당신들의 선동에 넘어가기를 바라야 한다.
== 배신자로 플레이하는 법 ==
사람을 죽이는 순서가 중요한 직업. 마지막 3명이 누구인지에 따라 자신의 승패가 달라진다.
만약 4인이면 간단하게 무법자를 죽여주고 보안관과 1대1을 펼치면 된다.
만약 5인이면 무법자->부관->무법자 순서대로 죽이고 보안관을 처치하면 된다.
6인이면 무법자->무법자->부관->무법자 순서대로 죽이고 보안관을 처치하면 된다.
7인이면 부관->무법자->무법자->부관->무법자 순으로 죽이고 보안관을 죽이면 된다.
8인이면 배신자->부관->무법자->무법자->부관->무법자 순으로 죽이면 된다.
977a550f55c017ff936adf55249baa4a586ae242
1310
1309
2021-10-17T12:48:37Z
Yeongjun
7622
wikitext
text/x-wiki
== 자신의 턴에 하는 일 ==
페이즈 0
자신의 앞에 다이너마이트나 감옥 카드가 놓여 있다면, 카드 펼치기를 해야한다. 즉, 플레잉 카드 덱에서 맨 위의 카드를 뽑아 무늬와 숫자를 확인하고 버린다. 여러 카드가 놓여 있을 경우 '다이너마이트 - 감옥 - 그 외' 순으로 처리한다. 감옥은 펼쳐진 카드의 무늬가 확인되면 버려지며, 효과가 발동된 다이너마이트도 버려진다.
페이즈 1
덱에서 카드를 2장 가져온다. 자신의 캐릭터가 카드 가져오기 관련 특수 능력이 있을 경우 특수 능력대로 카드를 가져온다.
페이즈 2
패의 카드를 쓸 수 있다면 원하는 만큼 사용한다. 기본적으론 사용 횟수에 제한은 없지만, 뱅은 캐릭터 능력이나 기타 장비 카드 등이 없다면 한 턴에 한 장만 사용 가능하고, 빗나감처럼 자신의 턴에 사용할 수 없는 카드 등 때문에 손에 든 카드를 사용할 수 없는 경우가 생긴다. 전략적으로 카드를 선택해서 남길 수도 있다.
페이즈 3
패에 있는 카드가 자신의 현재 라이프보다 많다면, 현재 라이프 수만큼만 카드를 소지하고 여분의 카드를 전부 버린다. 라이프보다 많을 때만 카드를 버릴 수 있지, 카드가 현재 라이프 수 이하일 때는 카드를 버리고 싶다고 임의로 카드를 버리는 것은 불가능하다.
자신의 턴이 끝나면 시계 방향, 즉 자신의 왼쪽에 앉은 플레이어의 턴이 시작된다.
게임은 보안관부터 시작하며, 보안관 오른쪽 사람의 턴이 끝날 때까지를 한 라운드라고 한다.
== 보안관으로 플레이하는 법 ==
무엇보다 부관을 빨리 찾아내야 되고 생명력 1이 늘어나기 때문에 잡화점에서 빗나감보다는 공격형 카드(인디언, 기관총, 결투 등)를 가져오는게 좋다. 맥주가 있다면 맥주를 가져오자.
4인이라면 배신자와 손잡고 무법자를 죽이되, 막타를 치도록 하자. 이때 들어오는 카드 3장이 의외로 크다. 그리고 남은 둘이서 개싸움을 할 동안 자신은 방어만 하면서 1 대 1 상황을 대비하자. 배신자는 무조건 무법자를 쏠 것이고, 무법자는 보안관을 쏘는 것 자체가 2 대 1 상황을 부르는 것이니 배신자를 쏠 것이다. 그 다음에 1 대 1 상황이 오면 살아남은 사람은 피가 2~3이거나 손패가 말라 있을 것이다. 이때 이기는 것은 식은 죽 먹기.
5인이면 부관이 있기 때문에 무법자 1명을 죽이고 각자 거리가 가까운 무법자 배신자 중 하나를 집중 공격하면 된다. 이때 서로 다른 사람을 공격하자.
6인이면 무법자가 3명이기에 매우 까다로워진다. 무법자 2명을 죽이고 5인 때와 똑같이 하면 된다. 무법자 죽이는 동안에 죽지 않기를 빈다....
7인이면 부관이 1명 더 늘어 더 수월해진다. 무법자 1명을 죽이고 5인 때처럼 하자.
8인이면 배신자가 늘어나 배신자가 부관부터 죽이면 곤란해진다. 배신자 1명, 무법자 1명을 죽이고 5인 때와 같이 하자.
== 부관으로 플레이하는 법 ==
5, 6인플에서는 자신과 보안관 빼고는 다 적이라고 생각하면 된다. 5인플에서는 무법자라 생각되는 사람을 치자. 다른 사람들에게는 적절한 정치질로 자신이 무법자를 치고 있다고 믿게 해야 한다.
이렇게 해서 무법자가 죽으면 보안-무법-배신-부관 상황이 되는데 이때는 배신자한테 죽지 않도록 조심해야 한다. 이렇게 버티면서 배신자나 무법자 하나가 죽으면 2대 1 상황이 되면서 게임 끝. 자신이 죽더라도 나를 죽인 사람은 보안관이 쉽게 죽인다. 이렇게 자신을 희생해서 보안관이 이기도록 해야 할 것이다.
== 무법자로 플레이하는 법 ==
보안관 카드 상황을 보고 생각하자.
1. 보안관이 가진 카드가 거의 없다.
무조건 보안관 명치를 친다. 이 행위를 무법자가 자기 정체를 드러낸다 하여 '무밍아웃'이라고 부른다. 무밍아웃 하는 순간 부관과 배신자가 견제하기 시작할 것인데, 이를 견디기 위한 방어 수단이 있으면 좋다.
2. 보안관 장비는 꽤 있는데 허리가 비었다.
우선 귀찮은 장비(술통, 야생마 등등)를 덜어낼 카드가 있는지 확인한다. 장비를 덜어낼 수 있다면, 장비를 덜어낸 다음 바로 공격하자. 장비를 덜어내지 못한다면, 차라리 부관으로 보이는 녀석을 무법이라 선동하면서 견제하자. 부관도 보안관에게 의심살 짓을 하는 놈이 꼭 하나씩은 있기 마련이다.
3. 보안관 장비는 부실한데 허리는 튼실하다.
광역기 돌리면서 허리부터 비운다. 보안관 핸드에 빗나감이 떨어졌다[31]고 생각되는 시점에서 무밍아웃 한다. 보안관은 엥간하면 광역기를 피하므로, 게틀링같은 빗나감 제출 광역기를 피하지 못한다면 높은 확률로 노빗이다.가끔 재수없으면 보안관 허리의 모든 카드가 빗나감일때도 있다(...)
4. 보안관 장비도 허리도 튼실하다.
보안관이 강캐를 잡고 카드 사기를 친 경우가 대부분이다. 안타깝지만, 이쯤되면 무법/배자가 이기기 정말 어려운 상태. 다만, 무법자들이 죽지 않은 상태에서 보안관을 도울 부관들을 다 떨어내면, 보안관은 오래 버티지 못한다. 고로 부관인 척 하며 부관들부터 쳐내자. 보안관이 당신들의 선동에 넘어가기를 바라야 한다.
== 배신자로 플레이하는 법 ==
사람을 죽이는 순서가 중요한 직업. 마지막 3명이 누구인지에 따라 자신의 승패가 달라진다.
만약 4인이면 간단하게 무법자를 죽여주고 보안관과 1대1을 펼치면 된다.
만약 5인이면 무법자->부관->무법자 순서대로 죽이고 보안관을 처치하면 된다.
6인이면 무법자->무법자->부관->무법자 순서대로 죽이고 보안관을 처치하면 된다.
7인이면 부관->무법자->무법자->부관->무법자 순으로 죽이고 보안관을 죽이면 된다.
8인이면 배신자->부관->무법자->무법자->부관->무법자 순으로 죽이면 된다.
ff1575543f25d116d33c0c011ef17892cb20c221
1311
1310
2021-10-17T12:49:33Z
Yeongjun
7622
/* 자신의 턴에 하는 일 */
wikitext
text/x-wiki
== 자신의 턴에 하는 일 ==
페이즈 0
자신의 앞에 다이너마이트나 감옥 카드가 놓여 있다면, 카드 펼치기를 해야한다. 즉, 플레잉 카드 덱에서 맨 위의 카드를 뽑아 무늬와 숫자를 확인하고 버린다. 여러 카드가 놓여 있을 경우 '다이너마이트 - 감옥 - 그 외' 순으로 처리한다. 감옥은 펼쳐진 카드의 무늬가 확인되면 버려지며, 효과가 발동된 다이너마이트도 버려진다.
페이즈 1
덱에서 카드를 2장 가져온다. 자신의 캐릭터가 카드 가져오기 관련 특수 능력이 있을 경우 특수 능력대로 카드를 가져온다.
페이즈 2
패의 카드를 쓸 수 있다면 원하는 만큼 사용한다. 기본적으론 사용 횟수에 제한은 없지만, 뱅은 캐릭터 능력이나 기타 장비 카드 등이 없다면 한 턴에 한 장만 사용 가능하고, 빗나감처럼 자신의 턴에 사용할 수 없는 카드 등 때문에 손에 든 카드를 사용할 수 없는 경우가 생긴다. 전략적으로 카드를 선택해서 남길 수도 있다.
페이즈 3
패에 있는 카드가 자신의 현재 라이프보다 많다면, 현재 라이프 수만큼만 카드를 소지하고 여분의 카드를 전부 버린다. 라이프보다 많을 때만 카드를 버릴 수 있지, 카드가 현재 라이프 수 이하일 때는 카드를 버리고 싶다고 임의로 카드를 버리는 것은 불가능하다.
자신의 턴이 끝나면 시계 방향, 즉 자신의 왼쪽에 앉은 플레이어의 턴이 시작된다.
게임은 보안관부터 시작하며, 보안관 오른쪽 사람의 턴이 끝날 때까지를 한 라운드라고 한다.
== 보안관으로 플레이하는 법 ==
무엇보다 부관을 빨리 찾아내야 되고 생명력 1이 늘어나기 때문에 잡화점에서 빗나감보다는 공격형 카드(인디언, 기관총, 결투 등)를 가져오는게 좋다. 맥주가 있다면 맥주를 가져오자.
4인이라면 배신자와 손잡고 무법자를 죽이되, 막타를 치도록 하자. 이때 들어오는 카드 3장이 의외로 크다. 그리고 남은 둘이서 개싸움을 할 동안 자신은 방어만 하면서 1 대 1 상황을 대비하자. 배신자는 무조건 무법자를 쏠 것이고, 무법자는 보안관을 쏘는 것 자체가 2 대 1 상황을 부르는 것이니 배신자를 쏠 것이다. 그 다음에 1 대 1 상황이 오면 살아남은 사람은 피가 2~3이거나 손패가 말라 있을 것이다. 이때 이기는 것은 식은 죽 먹기.
5인이면 부관이 있기 때문에 무법자 1명을 죽이고 각자 거리가 가까운 무법자 배신자 중 하나를 집중 공격하면 된다. 이때 서로 다른 사람을 공격하자.
6인이면 무법자가 3명이기에 매우 까다로워진다. 무법자 2명을 죽이고 5인 때와 똑같이 하면 된다. 무법자 죽이는 동안에 죽지 않기를 빈다....
7인이면 부관이 1명 더 늘어 더 수월해진다. 무법자 1명을 죽이고 5인 때처럼 하자.
8인이면 배신자가 늘어나 배신자가 부관부터 죽이면 곤란해진다. 배신자 1명, 무법자 1명을 죽이고 5인 때와 같이 하자.
== 부관으로 플레이하는 법 ==
5, 6인플에서는 자신과 보안관 빼고는 다 적이라고 생각하면 된다. 5인플에서는 무법자라 생각되는 사람을 치자. 다른 사람들에게는 적절한 정치질로 자신이 무법자를 치고 있다고 믿게 해야 한다.
이렇게 해서 무법자가 죽으면 보안-무법-배신-부관 상황이 되는데 이때는 배신자한테 죽지 않도록 조심해야 한다. 이렇게 버티면서 배신자나 무법자 하나가 죽으면 2대 1 상황이 되면서 게임 끝. 자신이 죽더라도 나를 죽인 사람은 보안관이 쉽게 죽인다. 이렇게 자신을 희생해서 보안관이 이기도록 해야 할 것이다.
== 무법자로 플레이하는 법 ==
보안관 카드 상황을 보고 생각하자.
1. 보안관이 가진 카드가 거의 없다.
무조건 보안관 명치를 친다. 이 행위를 무법자가 자기 정체를 드러낸다 하여 '무밍아웃'이라고 부른다. 무밍아웃 하는 순간 부관과 배신자가 견제하기 시작할 것인데, 이를 견디기 위한 방어 수단이 있으면 좋다.
2. 보안관 장비는 꽤 있는데 허리가 비었다.
우선 귀찮은 장비(술통, 야생마 등등)를 덜어낼 카드가 있는지 확인한다. 장비를 덜어낼 수 있다면, 장비를 덜어낸 다음 바로 공격하자. 장비를 덜어내지 못한다면, 차라리 부관으로 보이는 녀석을 무법이라 선동하면서 견제하자. 부관도 보안관에게 의심살 짓을 하는 놈이 꼭 하나씩은 있기 마련이다.
3. 보안관 장비는 부실한데 허리는 튼실하다.
광역기 돌리면서 허리부터 비운다. 보안관 핸드에 빗나감이 떨어졌다[31]고 생각되는 시점에서 무밍아웃 한다. 보안관은 엥간하면 광역기를 피하므로, 게틀링같은 빗나감 제출 광역기를 피하지 못한다면 높은 확률로 노빗이다.가끔 재수없으면 보안관 허리의 모든 카드가 빗나감일때도 있다(...)
4. 보안관 장비도 허리도 튼실하다.
보안관이 강캐를 잡고 카드 사기를 친 경우가 대부분이다. 안타깝지만, 이쯤되면 무법/배자가 이기기 정말 어려운 상태. 다만, 무법자들이 죽지 않은 상태에서 보안관을 도울 부관들을 다 떨어내면, 보안관은 오래 버티지 못한다. 고로 부관인 척 하며 부관들부터 쳐내자. 보안관이 당신들의 선동에 넘어가기를 바라야 한다.
== 배신자로 플레이하는 법 ==
사람을 죽이는 순서가 중요한 직업. 마지막 3명이 누구인지에 따라 자신의 승패가 달라진다.
만약 4인이면 간단하게 무법자를 죽여주고 보안관과 1대1을 펼치면 된다.
만약 5인이면 무법자->부관->무법자 순서대로 죽이고 보안관을 처치하면 된다.
6인이면 무법자->무법자->부관->무법자 순서대로 죽이고 보안관을 처치하면 된다.
7인이면 부관->무법자->무법자->부관->무법자 순으로 죽이고 보안관을 죽이면 된다.
8인이면 배신자->부관->무법자->무법자->부관->무법자 순으로 죽이면 된다.
985216a2b8be2d0d3eb95f98cd343df084c152a8
Gamehelpconnectfour
0
203
1312
2021-10-18T20:48:58Z
Ufm
6353
새 문서: ==목표== 커넥트포는 디스크 4개를 한 줄로 이으면 승리하는 2인 추상전략게임입니다. ==진행== 빨간색 플레이어가 선공이며, 각각 빨간색...
wikitext
text/x-wiki
==목표==
커넥트포는 디스크 4개를 한 줄로 이으면 승리하는 2인 추상전략게임입니다.
==진행==
빨간색 플레이어가 선공이며, 각각 빨간색과 노란색 디스크를 번갈아서 세로줄 하나에 수직으로 떨어뜨립니다.
따라서 한 세로줄에는 비어있는 칸 중 맨 아래쪽에만 디스크를 놓을 수 있습니다.
먼저 수직, 수평, 또는 대각선으로 자기 색깔의 디스크를 4개 이상 이으면 승리합니다.
사목이 나오지 않은 채 게임판이 꽉 차면 무승부입니다.
==오프닝 룰==
첫 수의 다양화와 선공의 유리함 해소를 위해 오프닝 룰을 적용할 수 있습니다.
* 파이 룰: 선공이 첫 수를 둔 뒤 후공이 색깔을 서로 맞바꿀 수 있습니다.
* 스왑 룰: 선공이 빨간색 디스크 1개, 노란색 디스크 1개, 빨간색 디스크 1개를 둡니다. 그 뒤 후공이 색깔을 서로 맞바꿀 수 있습니다.
==아레나 모드==
기본 6x7 게임판은 솔버가 너무 판쳐서 금지했습니다. 오프닝 룰은 상기한 이유에 따라 스왑 룰로 고정됩니다.
2021년 10월 기준 아레나 모드의 게임판 설정은 시즌이 바뀔 때마다 9x9와 8x9를 교대로 채용하는 로테이션 포맷입니다.
ba6bace773e82401db6bb90e9179cbfa4feacc77
1313
1312
2021-10-18T20:55:28Z
Ufm
6353
/* 진행 */
wikitext
text/x-wiki
==목표==
커넥트포는 디스크 4개를 한 줄로 이으면 승리하는 2인 추상전략게임입니다.
==진행==
빨간색 플레이어가 선공이며, 각각 빨간색과 노란색 디스크를 번갈아서 세로줄 하나에 수직으로 떨어뜨립니다.
따라서 한 세로줄에는 비어있는 칸 중 맨 아래쪽에만 디스크를 놓을 수 있습니다.
먼저 수직, 수평, 또는 대각선으로 자기 색깔의 디스크를 4개 이상 이으면 승리합니다.
사목이 나오지 않은 채 게임판이 꽉 차면 무승부입니다.
보드게임 아레나에서는 6x7, 8x9, 9x9, 10x10 게임판을 사용할 수 있습니다.
==오프닝 룰==
첫 수의 다양화와 선공의 유리함 해소를 위해 오프닝 룰을 적용할 수 있습니다.
* 파이 룰: 선공이 첫 수를 둔 뒤 후공이 색깔을 서로 맞바꿀 수 있습니다.
* 스왑 룰: 선공이 빨간색 디스크 1개, 노란색 디스크 1개, 빨간색 디스크 1개를 둡니다. 그 뒤 후공이 색깔을 서로 맞바꿀 수 있습니다.
==아레나 모드==
기본 6x7 게임판은 솔버가 너무 판쳐서 금지했습니다. 오프닝 룰은 상기한 이유에 따라 스왑 룰로 고정됩니다.
2021년 10월 기준 아레나 모드의 게임판 설정은 시즌이 바뀔 때마다 9x9와 8x9를 교대로 채용하는 로테이션 포맷입니다.
1724e4c1726d130a7d5efc0b7e703d1e4b51e043
Gamehelpgomoku
0
81
1314
1296
2021-10-21T11:00:43Z
Ufm
6353
wikitext
text/x-wiki
== 진행 ==
오목은 바둑판에서 바둑알로 두는 추상전략 게임입니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 흑이 선공입니다.
먼저 수직, 수평, 또는 대각선으로 돌 5개를 이으면 승리합니다.
== 옵션 ==
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 변형규칙 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
* '''기본''': 수직, 수평, 또는 대각선으로 정확히 돌 5개를 이으면 승리합니다. 6개 이상을 이으면 승리하지 않습니다.
* 카로: 수직, 수평, 또는 대각선으로 양쪽이 막히지 않게 돌 5개를 잇거나, 막힘 여부와 무관하게 돌 6개 이상을 이으면 승리합니다.
* 자유방식: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
=== 오프닝 룰 ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 흑으로 색깔 바꾸기
:# 백을 고른 뒤 백돌 두기
:# 백돌과 흑돌을 두고 색깔 선택권을 선공에게 넘기기
d8d763f1caa989373a81a632ccd65aa9ddf2dc9b
1315
1314
2021-10-21T11:05:28Z
Ufm
6353
wikitext
text/x-wiki
== 진행 ==
오목은 바둑판에서 바둑알로 두는 추상전략 게임입니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 흑이 선공입니다.
먼저 수직, 수평, 또는 대각선으로 돌 5개를 이으면 승리합니다.
== 옵션 ==
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 변형규칙 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
* '''기본''': 수직, 수평, 또는 대각선으로 정확히 돌 5개를 이으면 승리합니다. 6개 이상을 이으면 승리하지 않습니다.
* 카로: 수직, 수평, 또는 대각선으로 양쪽이 막히지 않게 돌 5개를 잇거나, 막힘 여부와 무관하게 돌 6개 이상을 이으면 승리합니다.
* 자유방식: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
=== 오프닝 룰 ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 흑으로 색깔 바꾸기
:# 백을 고른 뒤 백돌 두기
:# 백돌과 흑돌을 두고 색깔 선택권을 선공에게 넘기기
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 흑돌과 백돌, Swap2의 3번쨰 선택지에서 두는 2번째 백돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
d2e656b19918774ebb6fc7ac94e7ca8aa13a9a9c
1316
1315
2021-10-21T12:04:55Z
Ufm
6353
/* 확인 표시 */
wikitext
text/x-wiki
== 진행 ==
오목은 바둑판에서 바둑알로 두는 추상전략 게임입니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 흑이 선공입니다.
먼저 수직, 수평, 또는 대각선으로 돌 5개를 이으면 승리합니다.
== 옵션 ==
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 변형규칙 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
* '''기본''': 수직, 수평, 또는 대각선으로 정확히 돌 5개를 이으면 승리합니다. 6개 이상을 이으면 승리하지 않습니다.
* 카로: 수직, 수평, 또는 대각선으로 양쪽이 막히지 않게 돌 5개를 잇거나, 막힘 여부와 무관하게 돌 6개 이상을 이으면 승리합니다.
* 자유방식: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
=== 오프닝 룰 ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 흑으로 색깔 바꾸기
:# 백을 고른 뒤 백돌 두기
:# 백돌과 흑돌을 두고 색깔 선택권을 선공에게 넘기기
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 흑돌과 백돌, Swap2의 3번째 선택지에서 두는 2번째 백돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
b8ae171c4c14b425a86bedf40c2283b253029920
1317
1316
2021-10-21T16:08:57Z
Ufm
6353
/* 변형규칙 */
wikitext
text/x-wiki
== 진행 ==
오목은 바둑판에서 바둑알로 두는 추상전략 게임입니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 흑이 선공입니다.
먼저 수직, 수평, 또는 대각선으로 돌 5개를 이으면 승리합니다.
== 옵션 ==
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 변형규칙 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
* '''기본''': 수직, 수평, 또는 대각선으로 정확히 돌 5개를 이으면 승리합니다. 6개 이상을 이으면 승리하지 않습니다.
* 카로: 수직, 수평, 또는 대각선으로 양쪽 옆이 비도록 돌 5개를 잇거나, 막힘 여부와 무관하게 돌 6개 이상을 이으면 승리합니다.
* 자유방식: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
=== 오프닝 룰 ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 흑으로 색깔 바꾸기
:# 백을 고른 뒤 백돌 두기
:# 백돌과 흑돌을 두고 색깔 선택권을 선공에게 넘기기
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 흑돌과 백돌, Swap2의 3번째 선택지에서 두는 2번째 백돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
665140df19542d500565e570d2a27b6e22e2c16b
1318
1317
2021-10-21T21:44:35Z
Ufm
6353
/* 플레이어 설정 옵션 */
wikitext
text/x-wiki
== 진행 ==
오목은 바둑판에서 바둑알로 두는 추상전략 게임입니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 흑이 선공입니다.
먼저 수직, 수평, 또는 대각선으로 돌 5개를 이으면 승리합니다.
== 옵션 ==
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 변형규칙 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
* '''기본''': 수직, 수평, 또는 대각선으로 정확히 돌 5개를 이으면 승리합니다. 6개 이상을 이으면 승리하지 않습니다.
* 카로: 수직, 수평, 또는 대각선으로 양쪽 옆이 비도록 돌 5개를 잇거나, 막힘 여부와 무관하게 돌 6개 이상을 이으면 승리합니다.
* 자유방식: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
=== 오프닝 룰 ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 흑으로 색깔 바꾸기
:# 백을 고른 뒤 백돌 두기
:# 백돌과 흑돌을 두고 색깔 선택권을 선공에게 넘기기
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 흑돌과 백돌, Swap2의 3번째 선택지에서 두는 2번째 백돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
3e9a8eab9b0bb72c4ef9e89c48bea4bdbe8d3215
1319
1318
2021-10-25T11:55:28Z
Ufm
6353
wikitext
text/x-wiki
== 진행 ==
오목은 바둑판에서 바둑알로 두는 추상전략 게임입니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 흑이 선공입니다.
먼저 수직, 수평, 또는 대각선으로 돌 5개를 이으면 승리합니다.
== 옵션 ==
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 변형규칙 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
* '''기본''': 수직, 수평, 또는 대각선으로 정확히 돌 5개를 이으면 승리합니다. 6개 이상을 이으면 승리하지 않습니다.
* 카로: 수직, 수평, 또는 대각선으로 양쪽 옆이 비도록 돌 5개를 잇거나, 막힘 여부와 무관하게 돌 6개 이상을 이으면 승리합니다.
* 자유방식: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
=== 오프닝 룰 ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 흑으로 색깔 바꾸기
:# 백을 고른 뒤 백돌 두기
:# 백돌과 흑돌을 두고 색깔 선택권을 선공에게 넘기기
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 흑돌과 백돌, Swap2의 3번째 선택지에서 두는 2번째 백돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
155825f4f2696b4abe4cd2f6bb1e99e483ab59fa
Gamehelppente
0
204
1320
2021-10-25T12:08:03Z
Ufm
6353
새 문서: == 진행 == 바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다. 자기 색깔의 돌을 번갈아 빈 교차점에 두어 게...
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* 활성화: 누군가가 돌을 이어 게임을 끝낼 때, 다음 플레이어가 이어진 돌을 모두 잡아 게임 종료를 막을 수 있으면 게임이 계속 이어집니다.
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
=== 섞어 잡기 (다인) ===
이 옵션은 2인에서는 적용되지 않습니다.
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 흑돌과 백돌, Swap2의 3번째 선택지에서 두는 2번째 백돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== FAQ on variant options ==
Since various options can be combined with each other, here is an FAQ section to clarify rules implemented on BGA.
=== Self-capture position ===
These rules apply to even teammate's self-captures, so be extra careful in team games with self-capture!
==== Forbidden ====
When inserting stone in self-capture position is forbidden, forbidden move rule takes precedence over capture or win.
[[File:Penteselfcapture1.png]]
In this case, White cannot place stone on red circled intersection even the placement would capture 2 black stones.
This applies even if the placement would reach needed score to win the game or create a winning line.
In other words, that intersection is essentially 'locked' for White.
==== Self-capture ====
Capture three and mixed capture rules are applied to not only normal captures, but also to self-captures.
This makes things much more complex in multiplayer games.
[[File:Penteselfcapture2.png]]
When Red puts a stone on the red circled center while capture three is on, 2 normal captures and 3 self-captures will trigger at the same time.
As a result more than 1 player can lay claim to captured stones except left green stone and right yellow stone, which will be captured by Red.
So, who should take the other stones then?
In current implementation, the contested stones are destroyed into pieces.
In other words, no one scores for those stones and they simply vanish.
=== Overtime capture ===
Overtime capture is only possible when the next player can prevent another player winning the game by alignment.
In other words, a player may not perform overtime capture when:
* Another player achieved capture win
* Another player created multiple winning lines
* 2 or more other players satisfied winning condition at the same time
* Both sides of the only winning line are blocked, or open
* The only winning line is blocked on one side but not by the next player's stone, so the next player cannot capture the winning line (in multiplayer games)
=== No tiebreaker ===
Tiebreaker is not implemented. Every player meeting the winning condition shares the victory.
d1783f1680df050bf60b49a267d78af82216ce22
1321
1320
2021-10-25T12:08:23Z
Ufm
6353
/* 확인 표시 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* 활성화: 누군가가 돌을 이어 게임을 끝낼 때, 다음 플레이어가 이어진 돌을 모두 잡아 게임 종료를 막을 수 있으면 게임이 계속 이어집니다.
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
=== 섞어 잡기 (다인) ===
이 옵션은 2인에서는 적용되지 않습니다.
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== FAQ on variant options ==
Since various options can be combined with each other, here is an FAQ section to clarify rules implemented on BGA.
=== Self-capture position ===
These rules apply to even teammate's self-captures, so be extra careful in team games with self-capture!
==== Forbidden ====
When inserting stone in self-capture position is forbidden, forbidden move rule takes precedence over capture or win.
[[File:Penteselfcapture1.png]]
In this case, White cannot place stone on red circled intersection even the placement would capture 2 black stones.
This applies even if the placement would reach needed score to win the game or create a winning line.
In other words, that intersection is essentially 'locked' for White.
==== Self-capture ====
Capture three and mixed capture rules are applied to not only normal captures, but also to self-captures.
This makes things much more complex in multiplayer games.
[[File:Penteselfcapture2.png]]
When Red puts a stone on the red circled center while capture three is on, 2 normal captures and 3 self-captures will trigger at the same time.
As a result more than 1 player can lay claim to captured stones except left green stone and right yellow stone, which will be captured by Red.
So, who should take the other stones then?
In current implementation, the contested stones are destroyed into pieces.
In other words, no one scores for those stones and they simply vanish.
=== Overtime capture ===
Overtime capture is only possible when the next player can prevent another player winning the game by alignment.
In other words, a player may not perform overtime capture when:
* Another player achieved capture win
* Another player created multiple winning lines
* 2 or more other players satisfied winning condition at the same time
* Both sides of the only winning line are blocked, or open
* The only winning line is blocked on one side but not by the next player's stone, so the next player cannot capture the winning line (in multiplayer games)
=== No tiebreaker ===
Tiebreaker is not implemented. Every player meeting the winning condition shares the victory.
36accc7695709e4aab25c118ea07aaccff35a42a
1324
1321
2021-10-25T12:13:51Z
Ufm
6353
/* Forbidden */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* 활성화: 누군가가 돌을 이어 게임을 끝낼 때, 다음 플레이어가 이어진 돌을 모두 잡아 게임 종료를 막을 수 있으면 게임이 계속 이어집니다.
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
=== 섞어 잡기 (다인) ===
이 옵션은 2인에서는 적용되지 않습니다.
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== FAQ on variant options ==
Since various options can be combined with each other, here is an FAQ section to clarify rules implemented on BGA.
=== Self-capture position ===
These rules apply to even teammate's self-captures, so be extra careful in team games with self-capture!
==== 금수 ====
When inserting stone in self-capture position is forbidden, forbidden move rule takes precedence over capture or win.
[[File:Penteselfcapture1.png]]
In this case, White cannot place stone on red circled intersection even the placement would capture 2 black stones.
This applies even if the placement would reach needed score to win the game or create a winning line.
In other words, that intersection is essentially 'locked' for White.
==== Self-capture ====
Capture three and mixed capture rules are applied to not only normal captures, but also to self-captures.
This makes things much more complex in multiplayer games.
[[File:Penteselfcapture2.png]]
When Red puts a stone on the red circled center while capture three is on, 2 normal captures and 3 self-captures will trigger at the same time.
As a result more than 1 player can lay claim to captured stones except left green stone and right yellow stone, which will be captured by Red.
So, who should take the other stones then?
In current implementation, the contested stones are destroyed into pieces.
In other words, no one scores for those stones and they simply vanish.
=== Overtime capture ===
Overtime capture is only possible when the next player can prevent another player winning the game by alignment.
In other words, a player may not perform overtime capture when:
* Another player achieved capture win
* Another player created multiple winning lines
* 2 or more other players satisfied winning condition at the same time
* Both sides of the only winning line are blocked, or open
* The only winning line is blocked on one side but not by the next player's stone, so the next player cannot capture the winning line (in multiplayer games)
=== No tiebreaker ===
Tiebreaker is not implemented. Every player meeting the winning condition shares the victory.
2396b78182033c5d0a373a33f788e658f8503a75
1325
1324
2021-10-25T12:21:36Z
Ufm
6353
/* FAQ on variant options */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* 활성화: 누군가가 돌을 이어 게임을 끝낼 때, 다음 플레이어가 이어진 돌을 모두 잡아 게임 종료를 막을 수 있으면 게임이 계속 이어집니다.
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
=== 섞어 잡기 (다인) ===
이 옵션은 2인에서는 적용되지 않습니다.
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
이 경우 현재 보드게임 아레나 이식에서는 아무도 돌을 갖지 못하고, 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡을 수 있을 때에만 연장전이 발생합니다.
따라서 아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(또는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
2aa28b329ce7c684865b65fbd766b42e29b3ee83
1326
1325
2021-10-25T12:23:02Z
Ufm
6353
/* 자충수 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* 활성화: 누군가가 돌을 이어 게임을 끝낼 때, 다음 플레이어가 이어진 돌을 모두 잡아 게임 종료를 막을 수 있으면 게임이 계속 이어집니다.
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
=== 섞어 잡기 (다인) ===
이 옵션은 2인에서는 적용되지 않습니다.
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡을 수 있을 때에만 연장전이 발생합니다.
따라서 아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(또는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
4514a0d8bfcd1153cdb63854667a2f379abeddf7
1327
1326
2021-10-25T12:25:11Z
Ufm
6353
/* 연장전 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* 활성화: 누군가가 돌을 이어 게임을 끝낼 때, 다음 플레이어가 이어진 돌을 모두 잡아 게임 종료를 막을 수 있으면 게임이 계속 이어집니다.
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
=== 섞어 잡기 (다인) ===
이 옵션은 2인에서는 적용되지 않습니다.
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
따라서 아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(또는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
1491efe821e1df6c6afaeb86a4ae78ccf908db62
1328
1327
2021-10-25T12:27:06Z
Ufm
6353
/* 섞어 잡기 (다인) */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* '''15x15''': 오목의 표준 바둑판 크기입니다.
* 19x19: 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* 활성화: 누군가가 돌을 이어 게임을 끝낼 때, 다음 플레이어가 이어진 돌을 모두 잡아 게임 종료를 막을 수 있으면 게임이 계속 이어집니다.
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
따라서 아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(또는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
5edfca591e5d54167b2dfba39b2b3b2368705731
1329
1328
2021-10-27T12:27:50Z
Ufm
6353
/* 바둑판 크기 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* 활성화: 누군가가 돌을 이어 게임을 끝낼 때, 다음 플레이어가 이어진 돌을 모두 잡아 게임 종료를 막을 수 있으면 게임이 계속 이어집니다.
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
따라서 아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(또는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
af55f2da528c879f04ea83d688bfb2ad6297bf3d
1338
1329
2021-11-05T15:03:14Z
Ufm
6353
/* 연장전 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
따라서 아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(또는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
3c3200e9e8d627cbc715d2d15bbd0e96d8f4f6db
1339
1338
2021-11-05T15:03:35Z
Ufm
6353
/* 연장전 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
==== 연장전 (줄 잡기) ====
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
따라서 아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(또는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
0eac5d0c38df0928e713860072647cc767d28cde
1340
1339
2021-11-05T15:05:30Z
Ufm
6353
/* 연장전 (줄 잡기) */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
==== 연장전 (줄 잡기) ====
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
따라서 아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(또는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
연장전 규칙은 다음 플레이어의 차례에만 적용되므로, 자충수 규칙을 사용하는 게임에서 두 돌 사이에 돌을 끼워 승리 조건을 달성하는 경우에는 자충수나 연장전 없이 승리합니다.
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
7065d843c2e699cfdd662a4984ac95d25bf16c1e
1341
1340
2021-11-05T15:10:14Z
Ufm
6353
/* 연장전 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
==== 연장전 (줄 깨기) ====
누군가가 오목(팀전 이외의 다인전에서는 사목)을 만들었지만 사석 승리를 달성한 사람이 없으면 일단 연장전으로 넘어갑니다.
연장전 차례가 된 플레이어는 바둑판에서 오목(또는 사목)을 한 수로 끊을 수 있어야 합니다.
한 번에 오목(또는 사목) 여러 줄이 완성된 경우에는 한 수로 완성된 줄을 모두 끊어야 합니다.
완성된 줄이 장목인 경우 그 줄을 오목(또는 사목)으로 만드는 수는 게임 종료를 막을 수 없으므로 금수입니다.
아래의 줄 잡기 규칙과 달이 줄 깨기 연장전은 테이블 설정의 돌 잡기 규칙을 따르므로, 다인전에서 섞어 잡기 + 자충수 규칙을 쓰는 경우에는 자충수로 줄을 끊는 경우도 가능합니다.
==== 연장전 (줄 잡기) ====
아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(팀전 이외의 다인전에서는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
연장전 규칙은 다음 플레이어의 차례에만 적용되므로, 자충수 규칙을 사용하는 게임에서 두 돌 사이에 돌을 끼워 승리 조건을 달성하는 경우에는 자충수나 연장전 없이 승리합니다.
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
47c7586ffdd3fd992d0292c572fb900ec334838a
1342
1341
2021-11-05T15:11:08Z
Ufm
6353
/* 연장전 (줄 깨기) */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
==== 연장전 (줄 깨기) ====
누군가가 오목(팀전 이외의 다인전에서는 사목)을 만들었지만 사석 승리를 달성한 사람이 없으면 일단 연장전으로 넘어갑니다.
연장전 차례가 된 플레이어는 바둑판에서 오목(또는 사목)을 한 수로 끊을 수 있어야 합니다.
한 번에 오목(또는 사목) 여러 줄이 완성된 경우에는 한 수로 완성된 줄을 모두 끊어야 합니다.
완성된 줄이 장목인 경우 그 줄을 오목(또는 사목)으로 만드는 수는 게임 종료를 막을 수 없으므로 금수입니다.
이 조건에 맞는 수가 없거나, 자충수 금수 규칙이 적용된 상태이고 이 조건을 만족하는 수가 금수인 경우에는 패스를 눌러 기권해야 합니다.
아래의 줄 잡기 규칙과 달이 줄 깨기 연장전은 테이블 설정의 돌 잡기 규칙을 따르므로, 다인전에서 섞어 잡기 + 자충수 규칙을 쓰는 경우에는 자충수로 줄을 끊는 경우도 가능합니다.
==== 연장전 (줄 잡기) ====
아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(팀전 이외의 다인전에서는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
연장전 규칙은 다음 플레이어의 차례에만 적용되므로, 자충수 규칙을 사용하는 게임에서 두 돌 사이에 돌을 끼워 승리 조건을 달성하는 경우에는 자충수나 연장전 없이 승리합니다.
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
faaae50f8a23b5da0d360bbe83ebd43aa1278476
1343
1342
2021-11-05T15:13:24Z
Ufm
6353
/* 연장전 (줄 깨기) */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
==== 연장전 (줄 깨기) ====
누군가가 오목(팀전 이외의 다인전에서는 사목)을 만들었지만 사석 승리를 달성한 사람이 없으면 일단 연장전으로 넘어갑니다.
연장전 차례가 된 플레이어는 바둑판에서 오목(또는 사목)을 한 수로 끊을 수 있어야 합니다.
한 번에 오목(또는 사목) 여러 줄이 완성된 경우에는 한 수로 완성된 줄을 모두 끊어야 합니다.
완성된 줄이 장목인 경우 그 줄을 오목(또는 사목)으로 만드는 수는 게임 종료를 막을 수 없으므로 금수입니다.
이 조건에 맞는 수가 없거나, 자충수 금수 규칙이 적용된 상태이고 이 조건을 만족하는 수가 금수인 경우에는 패스를 눌러 기권해야 합니다.
줄 깨기 연장전은 테이블 설정의 돌 잡기 규칙을 따르므로, 다인전에서 섞어 잡기 + 자충수 규칙을 쓰는 경우에는 자충수로 줄을 끊는 경우도 가능합니다.
==== 연장전 (줄 잡기) ====
아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(팀전 이외의 다인전에서는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
연장전 규칙은 다음 플레이어의 차례에만 적용되므로, 자충수 규칙을 사용하는 게임에서 두 돌 사이에 돌을 끼워 승리 조건을 달성하는 경우에는 자충수나 연장전 없이 승리합니다.
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
da04add35a2197870be0d6c2b169e31d9feeeb08
1344
1343
2021-11-06T09:48:31Z
Ufm
6353
/* 연장전 (줄 깨기) */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개 이상을 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개 이상을 이으면 승리합니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
==== 연장전 (줄 깨기) ====
누군가가 오목(팀전 이외의 다인전에서는 사목)을 만들었지만 사석 승리를 달성한 사람이 없으면 일단 연장전으로 넘어갑니다.
연장전 차례가 된 플레이어는 바둑판에서 오목(또는 사목)을 한 수로 끊을 수 있어야 합니다.
한 번에 오목(또는 사목) 여러 줄이 완성된 경우에는 한 수로 완성된 줄을 모두 끊어야 합니다.
완성된 줄이 장목인 경우 그 줄을 오목(또는 사목)으로 만드는 수는 게임 종료를 막을 수 없으므로 금수입니다.
이 조건에 맞는 수가 없거나, 자충수 금수 규칙이 적용된 상태이고 이 조건을 만족하는 수가 금수인 경우에는 차례를 넘겨 기권해야 합니다.
줄 깨기 연장전은 테이블 설정의 돌 잡기 규칙을 따르므로, 다인전에서 섞어 잡기 + 자충수 규칙을 쓰는 경우에는 자충수로 줄을 끊는 경우도 가능합니다.
==== 연장전 (줄 잡기) ====
아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(팀전 이외의 다인전에서는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
연장전 규칙은 다음 플레이어의 차례에만 적용되므로, 자충수 규칙을 사용하는 게임에서 두 돌 사이에 돌을 끼워 승리 조건을 달성하는 경우에는 자충수나 연장전 없이 승리합니다.
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
c013260d47d2649f7ce3eec889bd5d7470a604b3
1346
1344
2021-11-07T21:33:44Z
Ufm
6353
/* 승리 조건 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개를 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개를 이으면 승리합니다.
==== 장목 ====
* '''승리''': 돌 5개 (팀전 이외의 다인전에서는 4개) 잇기에 더불어, 돌 6개 (팀전 이외의 다인전에서는 5개) 이상을 이어도 승리합니다.
* 장목 금수: 돌 6개 (팀전 이외의 다인전에서는 5개) 이상을 잇는 수는 금수입니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
==== 연장전 (줄 깨기) ====
누군가가 오목(팀전 이외의 다인전에서는 사목)을 만들었지만 사석 승리를 달성한 사람이 없으면 일단 연장전으로 넘어갑니다.
연장전 차례가 된 플레이어는 바둑판에서 오목(또는 사목)을 한 수로 끊을 수 있어야 합니다.
한 번에 오목(또는 사목) 여러 줄이 완성된 경우에는 한 수로 완성된 줄을 모두 끊어야 합니다.
완성된 줄이 장목인 경우 그 줄을 오목(또는 사목)으로 만드는 수는 게임 종료를 막을 수 없으므로 금수입니다.
이 조건에 맞는 수가 없거나, 자충수 금수 규칙이 적용된 상태이고 이 조건을 만족하는 수가 금수인 경우에는 차례를 넘겨 기권해야 합니다.
줄 깨기 연장전은 테이블 설정의 돌 잡기 규칙을 따르므로, 다인전에서 섞어 잡기 + 자충수 규칙을 쓰는 경우에는 자충수로 줄을 끊는 경우도 가능합니다.
==== 연장전 (줄 잡기) ====
아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(팀전 이외의 다인전에서는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
연장전 규칙은 다음 플레이어의 차례에만 적용되므로, 자충수 규칙을 사용하는 게임에서 두 돌 사이에 돌을 끼워 승리 조건을 달성하는 경우에는 자충수나 연장전 없이 승리합니다.
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
cd9d876a19a558f7375e871de6661dede0a3c2d6
1347
1346
2021-11-07T21:43:20Z
Ufm
6353
/* 장목 */
wikitext
text/x-wiki
== 진행 ==
바둑판에서 두는 이 게임에는 오목에 돌을 딸 수 있는 규칙이 추가되었습니다.
자기 색깔의 돌을 번갈아 빈 교차점에 두어 게임을 진행합니다. 백이 선공입니다.
이어진 상대 돌 2개를 자기 돌로 감싸면 돌을 딸 수 있습니다.
== 옵션 ==
보드게임 아레나 버전에서는 다양한 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로,''' ''연습 모드 전용 옵션은 이탤릭체로 표기했습니다.''
=== 바둑판 크기 ===
* ''9x9'': 빠른 게임이나 친선전용입니다.
* 13x13
* 15x15: 오목의 표준 바둑판 크기입니다.
* '''19x19''': 일반적인 바둑판 크기입니다.
=== 승리 조건 ===
바둑판 위쪽에 승리 조건이 표시됩니다.
설정과 무관하게 아래의 승리 조건은 항상 적용됩니다:
* 2인 모드 / 팀 모드: 수직, 수평, 또는 대각선으로 돌 5개를 이으면 승리합니다.
* 팀 모드 이외의 다인 모드: 수직, 수평, 또는 대각선으로 돌 4개를 이으면 승리합니다.
==== 장목 ====
* '''승리''': 돌 5개 (팀전 이외의 다인전에서는 4개) 잇기에 더불어, 돌 6개 (팀전 이외의 다인전에서는 5개) 이상을 이어도 승리합니다.
* 장목 금수: 돌 6개 (팀전 이외의 다인전에서는 5개) 이상을 잇는 수는 금수입니다.
자충수는 자충으로 잡히기 때문에 장목을 만들 수 없으므로 장목이 되는 위치에 두더라도 금수가 아닙니다.
==== 사석 승리 ====
* '''활성화''': 돌 5개 (팀전 이외의 다인전에서는 4개) 이상 잇기 외에도 돌 10개 (팀전 이외의 다인전에서는 8개) 이상을 따서 승리할 수 있습니다.
3개 따기 규칙을 사용하면 요구량이 돌 15개 (팀전 이외의 다인전에서는 12개) 이상으로 늘어납니다.
* 비활성화: 돌을 잡아서 승리할 수 없습니다.
이 옵션은 다인전에서는 비활성화하면 게임 진행 시간이 너무 늘어지므로 다인전에서의 비활성화 옵션을 금지했습니다.
=== 오프닝 룰 (2인) ===
처음 오프닝 룰 옵션 3개는 선공이 너무 유리해서 일반 모드에서는 사용할 수 없습니다.
* ''없음'': 오프닝 제약이 없습니다.
* ''Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 3칸 이상 떨어져야 합니다.
* ''Long Pro''
:- 선공의 1수는 천원에 두어야 합니다.
:- 후공은 1수를 아무 곳에나 둘 수 있습니다.
:- 선공의 2수는 천원에서 4칸 이상 떨어져야 합니다.
* Swap
:- 선공이 백돌, 흑돌, 백돌, 흑돌 순서대로 원하는 곳에 둡니다.
:- 후공은 원하는 색깔을 고릅니다.
:- 그 뒤 백이 돌을 두어 게임을 계속합니다.
* '''Swap2'''
:- 선공이 백돌, 흑돌, 백돌 순서대로 원하는 곳에 둡니다.
:- 후공에게는 3가지 선택지가 주어집니다.
:# 백으로 색깔 바꾸기
:# 흑을 고른 뒤 흑돌 두기
:# 흑돌과 백돌을 두고 색깔 선택권을 선공에게 넘기기
=== 3개 따기 ===
* 활성화: 3개 이어진 돌도 잡을 수 있습니다. 사석 승리에 필요한 돌의 수가 1.5배 늘어납니다.
* '''비활성화''': 2개 이어진 돌만 잡을 수 있습니다.
=== 자충수 규칙 ===
* '''자충수 없음''': 두 돌 사이에 자기 돌을 끼우면 아무 일도 일어나지 않습니다.
* 자충수: 두 돌 사이에 자기 돌을 끼우면 자충수가 됩니다. 끼워진 돌 묶음을 둘러싼 돌의 주인이 자충수로 따는 돌을 가져갑니다.
* 금수: 자충수가 되는 돌은 어떤 상황에서도 둘 수 없습니다.
=== 연장전 ===
* '''비활성화''': 게임 종료 상황이 되면 즉시 게임이 끝납니다.
* 정렬된 줄 깨기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 깨고 승리를 막을 수 있으면 게임이 계속됩니다.
* 정렬된 줄 잡기: 누군가가 돌을 이어 승리 조건을 달성해 게임이 끝날 때, 다음 플레이어가 돌을 두어 이어진 줄을 모두 잡고 승리를 막을 수 있으면 게임이 계속됩니다.
=== 섞어 잡기 (다인) ===
* '''활성화''': 서로 다른 색깔의 돌 묶음도 잡을 수 있습니다.
* 비활성화: 서로 같은 색깔의 이어진 돌만 잡을 수 있습니다.
=== 팀전 (4인) ===
* ''활성화'': 각자 2:2의 팀으로 대결합니다. 팀원끼리 돌을 잡을 수는 있지만 팀원의 돌로는 점수를 기록할 수 없습니다.
* '''비활성화''': 개인전으로 대결합니다.
보드게임 아레나 ELO 구조가 팀전의 ELO 변동을 제대로 계산하지 않으므로 팀전은 잘못된 ELO 변동을 막기 위해 연습 모드에서만 지원합니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 돌을 둔 뒤 확정 버튼이 표시됩니다. 확정 버튼을 눌러야 둔 수가 확정됩니다. 되돌릴 수 없는 행동은 빨간색 버튼으로 표시합니다.
* '''비활성화''': Swap과 Swap2의 첫 백돌과 흑돌, Swap2의 3번째 선택지에서 두는 2번째 흑돌을 제외한 모든 행동은 되돌릴 수 없습니다.
==== 마지막 수 강조 ====
* '''활성화''': 주황색 테두리로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 바둑판 주변에 좌표를 표시합니다.
* 비활성화: 바둑판 주변의 좌표를 표시하지 않습니다.
== 변형규칙 관련 자주 묻는 질문 ==
여러 변형규칙을 조합할 수 있으므로 현재 이식에서 적용되는 규칙을 정리했습니다.
=== 자충수 규칙 ===
자충수 규칙 설정은 팀원에게도 적용됩니다.
==== 금수 ====
자충수가 금수일 때는 자충수를 두어 다른 돌을 따거나 승리할 수 있을 때에도 그곳에 둘 수 없습니다.
[[File:Penteselfcapture1.png]]
위의 경우에는 빨간 원이 쳐진 칸에 백돌을 두면 흑돌 2개를 딸 수 있지만, 자충수가 되는 위치이므로 둘 수 없습니다.
자충수가 두는 위치에 돌을 두어 목표 점수에 도달하거나 오목을 만들 수 있더라도 자충수에는 돌을 둘 수 없습니다.
==== 자충수 ====
3개 따기나 섞어 잡기 규칙은 자충수에도 적용됩니다. 따라서 다인 게임에서의 양상이 더욱 복잡해집니다.
[[File:Penteselfcapture2.png]]
3개 따기와 섞어 잡기 규칙을 적용할 때 빨간색 돌을 빨간 원이 쳐진 칸에 두면, 왼쪽과 오른쪽에서 일반적인 돌 따기 2번, 가운데에서 자충수가 3번 겹쳐 발생합니다.
따라서 맨 왼쪽의 초록색 돌과 맨 오른쪽의 노란색 돌을 제외한 가운데의 나머지 돌은 2명 이상이 동시에 따게 됩니다.
한 돌을 여러 명이 따야 하는 경우, 현재 보드게임 아레나 이식에서는 아무도 그 돌을 갖지 못하고 돌은 따로 치워서 제거합니다.
=== 연장전 ===
돌을 이어서 승리 조건을 달성한 플레이어의 다음 플레이어가 이어진 돌을 잡아 게임 종료를 막을 수 있을 때에만 연장전이 발생합니다.
==== 연장전 (줄 깨기) ====
누군가가 오목(팀전 이외의 다인전에서는 사목)을 만들었지만 사석 승리를 달성한 사람이 없으면 일단 연장전으로 넘어갑니다.
연장전 차례가 된 플레이어는 바둑판에서 오목(또는 사목)을 한 수로 끊을 수 있어야 합니다.
한 번에 오목(또는 사목) 여러 줄이 완성된 경우에는 한 수로 완성된 줄을 모두 끊어야 합니다.
완성된 줄이 장목인 경우 그 줄을 오목(또는 사목)으로 만드는 수는 게임 종료를 막을 수 없으므로 금수입니다.
이 조건에 맞는 수가 없거나, 자충수 금수 규칙이 적용된 상태이고 이 조건을 만족하는 수가 금수인 경우에는 차례를 넘겨 기권해야 합니다.
줄 깨기 연장전은 테이블 설정의 돌 잡기 규칙을 따르므로, 다인전에서 섞어 잡기 + 자충수 규칙을 쓰는 경우에는 자충수로 줄을 끊는 경우도 가능합니다.
==== 연장전 (줄 잡기) ====
아래의 경우에는 연장전으로 넘어가지 않습니다:
* 다른 플레이어가 사석 승리를 달성
* 다른 플레이어가 한 번에 2개 이상의 오목(팀전 이외의 다인전에서는 사목)을 만듬
* 2명 이상이 동시에 승리 조건을 달성
* 이어진 돌의 양쪽이 모두 막혀있거나 모두 열려있음
* (다인전에서) 이어진 돌의 한쪽만이 막혀있지만 다음 플레이어의 돌로 막혀있지 않아 다음 플레이어가 이어진 돌을 딸 수 없음
연장전 규칙은 다음 플레이어의 차례에만 적용되므로, 자충수 규칙을 사용하는 게임에서 두 돌 사이에 돌을 끼워 승리 조건을 달성하는 경우에는 자충수나 연장전 없이 승리합니다.
=== 타이브레이커 없음 ===
현재 타이브레이커는 없습니다. 동시에 승리 조건을 달성한 플레이어가 여럿이라면 해당 플레이어끼리의 무승부가 됩니다.
eb6d7f3c6838a00e9b35530ce409e784276d25f8
파일:Penteselfcapture1.png
6
205
1322
2021-10-25T12:10:18Z
Ufm
6353
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
파일:Penteselfcapture2.png
6
206
1323
2021-10-25T12:10:23Z
Ufm
6353
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelpluckynumbers
0
207
1330
2021-11-03T10:02:07Z
YeolmuKimchi
7662
Translated by the original rule page. (https://boardgamearena.com/gamepanel?game=luckynumbers)
wikitext
text/x-wiki
<div class='wikicontent'><div><div class="mw-parser-output"><p>행운의 숫자는 행운에 예측을 곁들인 간단한 게임입니다.
</p>
</div></div></div><div class="pagesection"><div><div class="wikicontent"><h2><span class="mw-headline" id="Objective">목표</span></h2>
<p>목표는 격자 판을 16개의 숫자 타일로 모두 채우는 것입니다. 각 행의 숫자들은 왼쪽에서 오른쪽으로 갈수록 커져야 하며, 각 열의 숫자들은 위에서 아래로 갈수록 커져야 합니다. 같은 행이나 같은 열에서 같은 숫자를 두번 사용할 수는 없습니다.
</p><p>완성된 격자 판의 예시:
</p><p><a class="image" title="Lucky numbers.jpg"><img alt="Lucky numbers.jpg" src="https://doc.boardgamearena.com/images/1/1b/Lucky_numbers.jpg" decoding="async" width="386" height="388"/></a>
</p><p>처음으로 격자 판을 채운 플레이어가 승리합니다.
</p><p>여러 라운드에서의 점수 계산: 승자는 2점을 얻습니다. 다른 플레이어들은 각자의 격자 판에서 빈칸 하나에 1점씩 점수를 잃습니다.
</p>
</div></div></div><div class="pagesection"><div><div class="wikicontent"><h2><span class="mw-headline" id="Gameplay">게임 플레이</span></h2>
<p>각 플레이어마다, 1~20의 타일을 섞은 뒤, 대각선으로 4개의 숫자를 놓고 시작합니다.
</p><p>턴이 시작할 때, 더미에서 무작위 타일 하나를 뽑아오거나 (테이블에 타일이 있다면) 타일 하나를 손으로 가져옵니다.
</p><p>같은 행과 열에서 앞에 있는 타일보다 높은 수이거나, 뒤에 있는 타일보다 낮은 수일 경우 놓을 수 있습니다.<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 테이블에서 타일을 가져올 경우, 반드시 그 타일을 사용해야만 합니다.
</p><p>If you replace a tile on your grid, or choose to discard a drawn tile, that tile goes onto the table for the next player.격자 판 위의 타일과 교체하거나, 뽑은 타일을 버릴 경우, 그 타일은 테이블에 놓여져 다음 플레이어 차례로 넘어갑니다.
</p><br><p>
</p><br><p>
</p><p><span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 앞:왼쪽/위, 뒤:오른쪽/아래
</p>
71420bece30aabcb7ee1d9488b205c1ec37d2fde
1331
1330
2021-11-03T10:06:15Z
YeolmuKimchi
7662
wikitext
text/x-wiki
<div class='wikicontent'><div><div class="mw-parser-output"><p>행운의 숫자는 행운에 예측을 곁들인 간단한 게임입니다.
</p>
</div></div></div><div class="pagesection"><div><div class="wikicontent"><h2><span class="mw-headline" id="Objective">목표</span></h2>
<p>목표는 격자 판을 16개의 숫자 타일로 모두 채우는 것입니다. 각 행의 숫자들은 왼쪽에서 오른쪽으로 갈수록 커져야 하며, 각 열의 숫자들은 위에서 아래로 갈수록 커져야 합니다. 같은 행이나 같은 열에서 같은 숫자를 두번 사용할 수는 없습니다.
</p><p>완성된 격자 판의 예시:
</p><p><a class="image" title="Lucky numbers.jpg"><img alt="Lucky numbers.jpg" src="https://doc.boardgamearena.com/images/1/1b/Lucky_numbers.jpg" decoding="async" width="386" height="388"/></a>
</p><p>처음으로 격자 판을 채운 플레이어가 승리합니다.
</p><p>여러 라운드에서의 점수 계산: 승자는 2점을 얻습니다. 다른 플레이어들은 각자의 격자 판에서 빈칸 하나에 1점씩 점수를 잃습니다.
</p>
</div></div></div><div class="pagesection"><div><div class="wikicontent"><h2><span class="mw-headline" id="Gameplay">게임 플레이</span></h2>
<p>각 플레이어마다, 1~20의 타일을 섞은 뒤, 대각선으로 4개의 숫자를 놓고 시작합니다.
</p><p>턴이 시작할 때, 더미에서 무작위 타일 하나를 뽑아오거나 (테이블에 타일이 있다면) 타일 하나를 손으로 가져옵니다.
</p><p>같은 행과 열에서 앞에 있는 타일보다 높은 수이거나, 뒤에 있는 타일보다 낮은 수일 경우 놓을 수 있습니다.<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 테이블에서 타일을 가져올 경우, 반드시 그 타일을 사용해야만 합니다.
</p><p>격자 판 위의 타일과 교체하거나, 뽑은 타일을 버릴 경우, 그 타일은 테이블에 놓여져 다음 플레이어 차례로 넘어갑니다.
</p><br><p>
</p><br><p>
</p><p><span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 앞:왼쪽/위, 뒤:오른쪽/아래
</p>
76cabbab64c05cd0253f21526e1ef19fc1f51f35
1332
1331
2021-11-04T10:36:06Z
YeolmuKimchi
7662
If it doesn't work, I'll rollback it.
wikitext
text/x-wiki
<p>행운의 숫자는 행운에 예측을 곁들인 간단한 게임입니다.
</p>
<h2><span class="mw-headline" id="Objective">목표</span></h2>
<p>목표는 격자 판을 16개의 숫자 타일로 모두 채우는 것입니다. 각 행의 숫자들은 왼쪽에서 오른쪽으로 갈수록 커져야 하며, 각 열의 숫자들은 위에서 아래로 갈수록 커져야 합니다. 같은 행이나 같은 열에서 같은 숫자를 두번 사용할 수는 없습니다.
</p><p>완성된 격자 판의 예시:
</p><p><a class="image" title="Lucky numbers.jpg"><img alt="Lucky numbers.jpg" src="https://doc.boardgamearena.com/images/1/1b/Lucky_numbers.jpg" decoding="async" width="386" height="388"/></a>
</p><p>처음으로 격자 판을 채운 플레이어가 승리합니다.
</p><p>여러 라운드에서의 점수 계산: 승자는 2점을 얻습니다. 다른 플레이어들은 각자의 격자 판에서 빈칸 하나에 1점씩 점수를 잃습니다.
</p>
<h2><span class="mw-headline" id="Gameplay">게임 플레이</span></h2>
<p>각 플레이어마다, 1~20의 타일을 섞은 뒤, 대각선으로 4개의 숫자를 놓고 시작합니다.
</p><p>턴이 시작할 때, 더미에서 무작위 타일 하나를 뽑아오거나 (테이블에 타일이 있다면) 타일 하나를 손으로 가져옵니다.
</p><p>같은 행과 열에서 앞에 있는 타일보다 높은 수이거나, 뒤에 있는 타일보다 낮은 수일 경우 놓을 수 있습니다.<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 테이블에서 타일을 가져올 경우, 반드시 그 타일을 사용해야만 합니다.
</p><p>격자 판 위의 타일과 교체하거나, 뽑은 타일을 버릴 경우, 그 타일은 테이블에 놓여져 다음 플레이어 차례로 넘어갑니다.
</p><br><p>
</p><br><p>
</p><p><span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 앞:왼쪽/위, 뒤:오른쪽/아래
</p>
230be48b17800ad145c4d17dd8dc6ba2edeb86b1
1333
1332
2021-11-04T10:42:30Z
YeolmuKimchi
7662
Fixing image code
wikitext
text/x-wiki
<p>행운의 숫자는 행운에 예측을 곁들인 간단한 게임입니다.
</p>
<h2><span class="mw-headline" id="Objective">목표</span></h2>
<p>목표는 격자 판을 16개의 숫자 타일로 모두 채우는 것입니다. 각 행의 숫자들은 왼쪽에서 오른쪽으로 갈수록 커져야 하며, 각 열의 숫자들은 위에서 아래로 갈수록 커져야 합니다. 같은 행이나 같은 열에서 같은 숫자를 두번 사용할 수는 없습니다.
</p><p>완성된 격자 판의 예시:
</p><p><img alt="Lucky numbers.jpg" src="https://doc.boardgamearena.com/images/1/1b/Lucky_numbers.jpg" decoding="async" width="386" height="388"/>
</p><p>처음으로 격자 판을 채운 플레이어가 승리합니다.
</p><p>여러 라운드에서의 점수 계산: 승자는 2점을 얻습니다. 다른 플레이어들은 각자의 격자 판에서 빈칸 하나에 1점씩 점수를 잃습니다.
</p>
<h2><span class="mw-headline" id="Gameplay">게임 플레이</span></h2>
<p>각 플레이어마다, 1~20의 타일을 섞은 뒤, 대각선으로 4개의 숫자를 놓고 시작합니다.
</p><p>턴이 시작할 때, 더미에서 무작위 타일 하나를 뽑아오거나 (테이블에 타일이 있다면) 타일 하나를 손으로 가져옵니다.
</p><p>같은 행과 열에서 앞에 있는 타일보다 높은 수이거나, 뒤에 있는 타일보다 낮은 수일 경우 놓을 수 있습니다.<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 테이블에서 타일을 가져올 경우, 반드시 그 타일을 사용해야만 합니다.
</p><p>격자 판 위의 타일과 교체하거나, 뽑은 타일을 버릴 경우, 그 타일은 테이블에 놓여져 다음 플레이어 차례로 넘어갑니다.
</p><br><p>
</p><br><p>
</p><p><span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 앞:왼쪽/위, 뒤:오른쪽/아래
</p>
521e0fcc704648a306e750db95257a875e6373ce
1334
1333
2021-11-04T12:40:35Z
YeolmuKimchi
7662
Thanks to XCID (u=757940)
wikitext
text/x-wiki
행운의 숫자는 행운에 예측을 곁들인 간단한 게임입니다.
==목표==
목표는 격자 판을 16개의 숫자 타일로 모두 채우는 것입니다. 각 행의 숫자들은 왼쪽에서 오른쪽으로 갈수록 커져야 하며, 각 열의 숫자들은 위에서 아래로 갈수록 커져야 합니다. 같은 행이나 같은 열에서 같은 숫자를 두번 사용할 수는 없습니다.
완성된 격자 판의 예시:
[[File:Lucky numbers.jpg|Lucky numbers.jpg]]
처음으로 격자 판을 채운 플레이어가 승리합니다.
여러 라운드에서의 점수 계산: 승자는 2점을 얻습니다. 다른 플레이어들은 각자의 격자 판에서 빈칸 하나에 1점씩 점수를 잃습니다.
==게임 플레이==
각 플레이어마다, 1~20의 타일을 섞은 뒤, 대각선으로 4개의 숫자를 놓고 시작합니다.
턴이 시작할 때, 더미에서 무작위 타일 하나를 뽑아오거나 (테이블에 타일이 있다면) 타일 하나를 손으로 가져옵니다.
같은 행과 열에서 앞에 있는 타일보다 높은 수이거나, 뒤에 있는 타일보다 낮은 수일 경우 놓을 수 있습니다.<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 테이블에서 타일을 가져올 경우, 반드시 그 타일을 사용해야만 합니다.
격자 판 위의 타일과 교체하거나, 뽑은 타일을 버릴 경우, 그 타일은 테이블에 놓여져 다음 플레이어 차례로 넘어갑니다.
<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 앞:왼쪽/위, 뒤:오른쪽/아래
2219713f97f22ee83ad08b970619bfd76e8362c0
1335
1334
2021-11-04T12:42:45Z
YeolmuKimchi
7662
Maybe it's the final version for me. I fixed everything which doesn't work as I can.
wikitext
text/x-wiki
행운의 숫자는 행운에 예측을 곁들인 간단한 게임입니다.
==목표==
목표는 격자 판을 16개의 숫자 타일로 모두 채우는 것입니다. 각 행의 숫자들은 왼쪽에서 오른쪽으로 갈수록 커져야 하며, 각 열의 숫자들은 위에서 아래로 갈수록 커져야 합니다. 같은 행이나 같은 열에서 같은 숫자를 두번 사용할 수는 없습니다.
완성된 격자 판의 예시:
[[File:Lucky_numbers.jpg|Lucky_numbers.jpg]]
처음으로 격자 판을 채운 플레이어가 승리합니다.
여러 라운드에서의 점수 계산: 승자는 2점을 얻습니다. 다른 플레이어들은 각자의 격자 판에서 빈칸 하나에 1점씩 점수를 잃습니다.
==게임 플레이==
각 플레이어마다, 1~20의 타일을 섞은 뒤, 대각선으로 4개의 숫자를 놓고 시작합니다.
턴이 시작할 때, 더미에서 무작위 타일 하나를 뽑아오거나 (테이블에 타일이 있다면) 타일 하나를 손으로 가져옵니다.
같은 행과 열에서 앞에 있는 타일보다 높은 수이거나, 뒤에 있는 타일보다 낮은 수일 경우 놓을 수 있습니다.<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 테이블에서 타일을 가져올 경우, 반드시 그 타일을 사용해야만 합니다.
격자 판 위의 타일과 교체하거나, 뽑은 타일을 버릴 경우, 그 타일은 테이블에 놓여져 다음 플레이어 차례로 넘어갑니다.
<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 앞:왼쪽/위, 뒤:오른쪽/아래
8d7ed1f65b3e4e0ca74b282cdd5d489d17ee85e3
1337
1335
2021-11-04T16:00:38Z
YeolmuKimchi
7662
I learned file uploading so
wikitext
text/x-wiki
행운의 숫자는 행운에 예측을 곁들인 간단한 게임입니다.
==목표==
목표는 격자 판을 16개의 숫자 타일로 모두 채우는 것입니다. 각 행의 숫자들은 왼쪽에서 오른쪽으로 갈수록 커져야 하며, 각 열의 숫자들은 위에서 아래로 갈수록 커져야 합니다. 같은 행이나 같은 열에서 같은 숫자를 두번 사용할 수는 없습니다.
완성된 격자 판의 예시:
[[File:Lucky_numbers2.jpg|Lucky_numbers2.jpg]]
처음으로 격자 판을 채운 플레이어가 승리합니다.
여러 라운드에서의 점수 계산: 승자는 2점을 얻습니다. 다른 플레이어들은 각자의 격자 판에서 빈칸 하나에 1점씩 점수를 잃습니다.
==게임 플레이==
각 플레이어마다, 1~20의 타일을 섞은 뒤, 대각선으로 4개의 숫자를 놓고 시작합니다.
턴이 시작할 때, 더미에서 무작위 타일 하나를 뽑아오거나 (테이블에 타일이 있다면) 타일 하나를 손으로 가져옵니다.
같은 행과 열에서 앞에 있는 타일보다 높은 수이거나, 뒤에 있는 타일보다 낮은 수일 경우 놓을 수 있습니다.<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 테이블에서 타일을 가져올 경우, 반드시 그 타일을 사용해야만 합니다.
격자 판 위의 타일과 교체하거나, 뽑은 타일을 버릴 경우, 그 타일은 테이블에 놓여져 다음 플레이어 차례로 넘어갑니다.
<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 앞:왼쪽/위, 뒤:오른쪽/아래
6d049a839fdf9e6983e4f847ab7a326bfd84e5a6
파일:Lucky numbers2.jpg
6
208
1336
2021-11-04T15:59:21Z
YeolmuKimchi
7662
The origin of this file is the original Lucky Numbers help page.
wikitext
text/x-wiki
== 파일의 설명 ==
The origin of this file is the original Lucky Numbers help page.
a764e3957ade5750d972e62228fbe8d9f858f769
Tips cardiceo
0
209
1345
2021-11-07T14:24:52Z
Ohayo1231
7678
새 문서: 사용할 주사위는 다음 플레이어의 옵션에 영향을 미칩니다. 사용하지 않는 주사위는 "잠금"되어 다음 플레이어가 주사위를 굴릴 수 없습...
wikitext
text/x-wiki
사용할 주사위는 다음 플레이어의 옵션에 영향을 미칩니다.
사용하지 않는 주사위는 "잠금"되어 다음 플레이어가 주사위를 굴릴 수 없습니다. 동일한 값을 가진 둘 이상의 주사위를 선택할 수 있는 경우 이 점을 명심하십시오. 예를 들어, 모든 주사위에 3이 있고 3 카드가 있다면 4면 다이를 사용하세요. 그러면 다음 플레이어의 8면 다이와 12면 다이의 값이 3으로 잠기고 사용자가 사용한 4면 다이의 값만 굴릴 수 있습니다. 그들이 얻을 수 있는 최대 합계는 10이 될 것이고, 4면 다이에 4를 얻을 수 있는 경우에만 가능합니다.
d25f7c76c8e438ebc4030eab59ef65b03aed43cf
Gamehelptumbleweed
0
210
1348
2021-11-21T05:38:13Z
Ufm
6353
새 문서: == 게임 설명 == 텀블위드는 정육각형 헥스 게임판에서 말 더미를 쌓는 2인 게임입니다. 게임판에 놓인 더미는 서로 직선으로 이어졌으며...
wikitext
text/x-wiki
== 게임 설명 ==
텀블위드는 정육각형 헥스 게임판에서 말 더미를 쌓는 2인 게임입니다.
게임판에 놓인 더미는 서로 직선으로 이어졌으며 그 더미와 칸 사이에 다른 더미가 없는 칸을 '볼' 수 있습니다. 각자 번갈아 자기 더미가 볼 수 있는 칸에 더미를 놓습니다. 새로 놓는 더미의 높이는 그 더미를 볼 수 있는 자기 더미의 수와 같습니다. 상대 더미를 잡거나 자기 더미를 강화해 이미 놓인 더미를 더 높은 새 더미로 교체할 수도 있습니다.
게임을 시작하기 전에 선공이 게임판의 초기 배치를 결정한 뒤 후공이 어느 색깔로 게임을 진행할지 결정합니다. 초기 배치 단계에는 중립 말 2개가 쌓인 더미 하나와, 선공이 원하는 위치에 놓는 각 플레이어의 시작 토큰 하나를 배치합니다.
두 플레이어 모두 더 이상 수를 둘 수 없거나 두 명이 연속으로 차례를 넘기면 게임이 끝납니다. 더 많은 칸을 차지한 플레이어가 승리합니다.
텀블위드는 보드게임긱에서 2020년에 최고의 2인 조합 게임으로 뽑혔습니다.
이 설명은 보드게임긱의 텀블위드 페이지에서 가져왔습니다.
== 게임 종료 알림 ==
양쪽 플레이어 모두 3번의 차례 동안 상대 더미를 잡거나 통제하는 칸을 공격하지 않으면 알림이 표시됩니다.
이 상태가 앞으로 각자 1번씩 더 계속되면 게임이 자동으로 끝납니다.
각자의 영역이 확정되었다면 서로 차례를 넘겨 게임을 마치기를 권장합니다.
== 설정 ==
보드게임 아레나 버전에서는 새로운 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로 표기했습니다.'''
=== 게임판 크기 ===
* '''6x6x6''': 가장 작은 크기의 게임판입니다. 초보자나 속기전에 추천합니다.
* 8x8x8: 경쟁전용 표준 게임판입니다.
* 10x10x10: 더 큰 크기의 게임판입니다. 턴 기반 게임이나 복잡한 게임에 추천합니다.
* 11x11x11: 가장 큰 크기의 게임판입니다. 턴 기반 게임이나 깊이 있는 게임에 추천합니다.
=== 초기 배치 ===
* '''기본 설정''': 중립 더미를 중앙에 놓습니다.
* 자유 설정: 게임 시작 시의 선공이 중립 더미를 놓습니다.
=== 플레이어 보조 기능 ===
* 초보자: 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸과 통제하고 있는 빈칸의 수를 합쳐서 보여줍니다. 통제한 칸은 강조 표시, 잡을 수 있는 더미는 테두리로 표시합니다. 둔 수를 확인할 때, 상대가 바로 잡을 수 있는 더미는 회색으로 표시합니다.
통제하고 있는 칸과 잡을 수 있는 더미의 강조 표시는 플레이어 설정 옵션으로 켜고 끌 수 있습니다.
* '''중급자''': 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸과 통제하고 있는 빈칸의 수를 합쳐서 보여줍니다. 둔 수를 확인할 때, 상대가 바로 잡을 수 있는 더미는 회색으로 표시합니다.
* 전문가: 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸만 계산합니다. 통제하고 있는 빈칸의 수는 게임이 끝날 때에 보여줍니다. 둔 수를 확인할 때에는 놓이는 더미의 색깔만 표시합니다.
현실의 게임처럼 진행됩니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* 활성화: 육각형 칸을 누르면 놓을 더미를 미리 볼 수 있습니다. 미리보기 더미를 다시 눌러야 둔 수가 확정됩니다.
* '''비활성화''': 칸을 누르면 미리보기 없이 바로 더미를 놓습니다.
전문가 모드에서는 미리보기에서 놓을 더미의 색깔만 표시합니다.
==== 마지막 수 강조 ====
* '''활성화''': 노란색 톤으로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 게임판 주변에 좌표를 표시합니다.
* 비활성화: 게임판 주변의 좌표를 표시하지 않습니다.
==== 영향력 표시 (초보자 모드 한정) ====
* '''활성화''': 통제 상태의 칸은 통제한 플레이어의 색깔로 표시합니다. 분홍색 칸은 두 플레이어의 영향력이 같은 칸입니다.
* 비활성화: 빈칸의 영향력을 표시하지 않습니다.
이 옵션은 중급자와 전문가 모드에서는 아무 효과가 없습니다.
==== 잡을 수 있는 더미 강조 (초보자 모드 한정) ====
* '''활성화''': 잡을 수 있는 더미의 테두리 색깔이 바뀝니다. 상대가 잡을 수 있는 더미의 색깔만 바뀌며, 강화만 할 수 있는 더미는 그대로입니다.
* 비활성화: 잡을 수 있는 더미의 색깔이 바뀌지 않습니다.
이 옵션은 중급자와 전문가 모드에서는 아무 효과가 없습니다.
==== 화질 ====
* 높음: SVG 이미지를 사용합니다. 모바일에서는 (특히 화면을 확대/축소할 때) 성능이 저하됩니다. 데스크탑에서 추천합니다.
* '''중간''': PNG 이미지를 사용합니다. 픽셀 단위 어긋남이 발생하지만 더 빠릅니다. 모바일에서 추천합니다.
4208777fa59fcff2e0ec2a85ab55558e3b59ee71
1349
1348
2021-11-21T05:39:57Z
Ufm
6353
/* 확인 표시 */
wikitext
text/x-wiki
== 게임 설명 ==
텀블위드는 정육각형 헥스 게임판에서 말 더미를 쌓는 2인 게임입니다.
게임판에 놓인 더미는 서로 직선으로 이어졌으며 그 더미와 칸 사이에 다른 더미가 없는 칸을 '볼' 수 있습니다. 각자 번갈아 자기 더미가 볼 수 있는 칸에 더미를 놓습니다. 새로 놓는 더미의 높이는 그 더미를 볼 수 있는 자기 더미의 수와 같습니다. 상대 더미를 잡거나 자기 더미를 강화해 이미 놓인 더미를 더 높은 새 더미로 교체할 수도 있습니다.
게임을 시작하기 전에 선공이 게임판의 초기 배치를 결정한 뒤 후공이 어느 색깔로 게임을 진행할지 결정합니다. 초기 배치 단계에는 중립 말 2개가 쌓인 더미 하나와, 선공이 원하는 위치에 놓는 각 플레이어의 시작 토큰 하나를 배치합니다.
두 플레이어 모두 더 이상 수를 둘 수 없거나 두 명이 연속으로 차례를 넘기면 게임이 끝납니다. 더 많은 칸을 차지한 플레이어가 승리합니다.
텀블위드는 보드게임긱에서 2020년에 최고의 2인 조합 게임으로 뽑혔습니다.
이 설명은 보드게임긱의 텀블위드 페이지에서 가져왔습니다.
== 게임 종료 알림 ==
양쪽 플레이어 모두 3번의 차례 동안 상대 더미를 잡거나 통제하는 칸을 공격하지 않으면 알림이 표시됩니다.
이 상태가 앞으로 각자 1번씩 더 계속되면 게임이 자동으로 끝납니다.
각자의 영역이 확정되었다면 서로 차례를 넘겨 게임을 마치기를 권장합니다.
== 설정 ==
보드게임 아레나 버전에서는 새로운 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로 표기했습니다.'''
=== 게임판 크기 ===
* '''6x6x6''': 가장 작은 크기의 게임판입니다. 초보자나 속기전에 추천합니다.
* 8x8x8: 경쟁전용 표준 게임판입니다.
* 10x10x10: 더 큰 크기의 게임판입니다. 턴 기반 게임이나 복잡한 게임에 추천합니다.
* 11x11x11: 가장 큰 크기의 게임판입니다. 턴 기반 게임이나 깊이 있는 게임에 추천합니다.
=== 초기 배치 ===
* '''기본 설정''': 중립 더미를 중앙에 놓습니다.
* 자유 설정: 게임 시작 시의 선공이 중립 더미를 놓습니다.
=== 플레이어 보조 기능 ===
* 초보자: 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸과 통제하고 있는 빈칸의 수를 합쳐서 보여줍니다. 통제한 칸은 강조 표시, 잡을 수 있는 더미는 테두리로 표시합니다. 둔 수를 확인할 때, 상대가 바로 잡을 수 있는 더미는 회색으로 표시합니다.
통제하고 있는 칸과 잡을 수 있는 더미의 강조 표시는 플레이어 설정 옵션으로 켜고 끌 수 있습니다.
* '''중급자''': 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸과 통제하고 있는 빈칸의 수를 합쳐서 보여줍니다. 둔 수를 확인할 때, 상대가 바로 잡을 수 있는 더미는 회색으로 표시합니다.
* 전문가: 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸만 계산합니다. 통제하고 있는 빈칸의 수는 게임이 끝날 때에 보여줍니다. 둔 수를 확인할 때에는 놓이는 더미의 색깔만 표시합니다.
현실의 게임처럼 진행됩니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* '''활성화''': 육각형 칸을 누르면 놓을 더미를 미리 볼 수 있습니다. 미리보기 더미를 다시 눌러야 둔 수가 확정됩니다.
* 비활성화: 칸을 누르면 미리보기 없이 바로 더미를 놓습니다.
전문가 모드에서는 미리보기에서 놓을 더미의 색깔만 표시합니다.
==== 마지막 수 강조 ====
* '''활성화''': 노란색 톤으로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 게임판 주변에 좌표를 표시합니다.
* 비활성화: 게임판 주변의 좌표를 표시하지 않습니다.
==== 영향력 표시 (초보자 모드 한정) ====
* '''활성화''': 통제 상태의 칸은 통제한 플레이어의 색깔로 표시합니다. 분홍색 칸은 두 플레이어의 영향력이 같은 칸입니다.
* 비활성화: 빈칸의 영향력을 표시하지 않습니다.
이 옵션은 중급자와 전문가 모드에서는 아무 효과가 없습니다.
==== 잡을 수 있는 더미 강조 (초보자 모드 한정) ====
* '''활성화''': 잡을 수 있는 더미의 테두리 색깔이 바뀝니다. 상대가 잡을 수 있는 더미의 색깔만 바뀌며, 강화만 할 수 있는 더미는 그대로입니다.
* 비활성화: 잡을 수 있는 더미의 색깔이 바뀌지 않습니다.
이 옵션은 중급자와 전문가 모드에서는 아무 효과가 없습니다.
==== 화질 ====
* 높음: SVG 이미지를 사용합니다. 모바일에서는 (특히 화면을 확대/축소할 때) 성능이 저하됩니다. 데스크탑에서 추천합니다.
* '''중간''': PNG 이미지를 사용합니다. 픽셀 단위 어긋남이 발생하지만 더 빠릅니다. 모바일에서 추천합니다.
bee870649c4ad683170199fd3ff3e8537768e5a9
1350
1349
2021-11-26T02:23:23Z
Ufm
6353
/* 플레이어 설정 옵션 */
wikitext
text/x-wiki
== 게임 설명 ==
텀블위드는 정육각형 헥스 게임판에서 말 더미를 쌓는 2인 게임입니다.
게임판에 놓인 더미는 서로 직선으로 이어졌으며 그 더미와 칸 사이에 다른 더미가 없는 칸을 '볼' 수 있습니다. 각자 번갈아 자기 더미가 볼 수 있는 칸에 더미를 놓습니다. 새로 놓는 더미의 높이는 그 더미를 볼 수 있는 자기 더미의 수와 같습니다. 상대 더미를 잡거나 자기 더미를 강화해 이미 놓인 더미를 더 높은 새 더미로 교체할 수도 있습니다.
게임을 시작하기 전에 선공이 게임판의 초기 배치를 결정한 뒤 후공이 어느 색깔로 게임을 진행할지 결정합니다. 초기 배치 단계에는 중립 말 2개가 쌓인 더미 하나와, 선공이 원하는 위치에 놓는 각 플레이어의 시작 토큰 하나를 배치합니다.
두 플레이어 모두 더 이상 수를 둘 수 없거나 두 명이 연속으로 차례를 넘기면 게임이 끝납니다. 더 많은 칸을 차지한 플레이어가 승리합니다.
텀블위드는 보드게임긱에서 2020년에 최고의 2인 조합 게임으로 뽑혔습니다.
이 설명은 보드게임긱의 텀블위드 페이지에서 가져왔습니다.
== 게임 종료 알림 ==
양쪽 플레이어 모두 3번의 차례 동안 상대 더미를 잡거나 통제하는 칸을 공격하지 않으면 알림이 표시됩니다.
이 상태가 앞으로 각자 1번씩 더 계속되면 게임이 자동으로 끝납니다.
각자의 영역이 확정되었다면 서로 차례를 넘겨 게임을 마치기를 권장합니다.
== 설정 ==
보드게임 아레나 버전에서는 새로운 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로 표기했습니다.'''
=== 게임판 크기 ===
* '''6x6x6''': 가장 작은 크기의 게임판입니다. 초보자나 속기전에 추천합니다.
* 8x8x8: 경쟁전용 표준 게임판입니다.
* 10x10x10: 더 큰 크기의 게임판입니다. 턴 기반 게임이나 복잡한 게임에 추천합니다.
* 11x11x11: 가장 큰 크기의 게임판입니다. 턴 기반 게임이나 깊이 있는 게임에 추천합니다.
=== 초기 배치 ===
* '''기본 설정''': 중립 더미를 중앙에 놓습니다.
* 자유 설정: 게임 시작 시의 선공이 중립 더미를 놓습니다.
=== 플레이어 보조 기능 ===
* 초보자: 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸과 통제하고 있는 빈칸의 수를 합쳐서 보여줍니다. 통제한 칸은 강조 표시, 잡을 수 있는 더미는 테두리로 표시합니다. 둔 수를 확인할 때, 상대가 바로 잡을 수 있는 더미는 회색으로 표시합니다.
통제하고 있는 칸과 잡을 수 있는 더미의 강조 표시는 플레이어 설정 옵션으로 켜고 끌 수 있습니다.
* '''중급자''': 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸과 통제하고 있는 빈칸의 수를 합쳐서 보여줍니다. 둔 수를 확인할 때, 상대가 바로 잡을 수 있는 더미는 회색으로 표시합니다.
* 전문가: 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸만 계산합니다. 통제하고 있는 빈칸의 수는 게임이 끝날 때에 보여줍니다. 둔 수를 확인할 때에는 놓이는 더미의 색깔만 표시합니다.
현실의 게임처럼 진행됩니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* '''활성화''': 육각형 칸을 누르면 놓을 더미를 미리 볼 수 있습니다. 미리보기 더미를 다시 눌러야 둔 수가 확정됩니다.
* 비활성화: 칸을 누르면 미리보기 없이 바로 더미를 놓습니다.
전문가 모드에서는 미리보기에서 놓을 더미의 색깔만 표시합니다.
==== 마지막 수 강조 ====
* '''활성화''': 노란색 톤으로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 게임판 주변에 좌표를 표시합니다.
* 비활성화: 게임판 주변의 좌표를 표시하지 않습니다.
==== 영향력 표시 (초보자 모드 한정) ====
* '''활성화''': 통제 상태의 칸은 통제한 플레이어의 색깔로 표시합니다. 분홍색 칸은 두 플레이어의 영향력이 같은 칸입니다.
* 비활성화: 빈칸의 영향력을 표시하지 않습니다.
이 옵션은 중급자와 전문가 모드에서는 아무 효과가 없습니다.
==== 잡을 수 있는 더미 강조 (초보자 모드 한정) ====
* '''활성화''': 잡을 수 있는 더미의 테두리 색깔이 바뀝니다. 상대가 잡을 수 있는 더미의 색깔만 바뀌며, 강화만 할 수 있는 더미는 그대로입니다.
* 비활성화: 잡을 수 있는 더미의 색깔이 바뀌지 않습니다.
이 옵션은 중급자와 전문가 모드에서는 아무 효과가 없습니다.
34dc0022ff618025be1dd1207ee50211ea0e8821
Gamehelppyrgos
0
211
1351
2021-11-30T05:45:03Z
Ufm
6353
새 문서: == 구성품 == * 4x4 격자 게임판 * 2색의 말 15개씩 (사각형 말 5개, 삼각형 말 5개, 원통 말 5개) == 게임 컨셉 == 피르고스는 간단한 2인 추상...
wikitext
text/x-wiki
== 구성품 ==
* 4x4 격자 게임판
* 2색의 말 15개씩 (사각형 말 5개, 삼각형 말 5개, 원통 말 5개)
== 게임 컨셉 ==
피르고스는 간단한 2인 추상전략게임입니다.
플레이어는 탑을 짓는 건축가가 됩니다. 자기가 놓는 말로 다음에 상대가 어디에 말을 놓을지 결정합니다. 먼저 탑 3개를 차지하면 승리합니다.
== 준비 ==
각자 색깔을 결정하고 자기 앞에 자기 색깔의 말 15개를 둡니다.
== 게임 방식 ==
자기 차례에는 아래의 규칙에 따라 자기 말 하나를 골라 놓습니다.
1) 한 칸에는 색깔에 무관하게 삼각형, 사각형, 원통 하나씩을 배치할 수 있습니다. 말이 칸에 놓인 순서는 게임에 영향을 미치지 않습니다.
2) '''사각형'''을 놓으면 다음 플레이어는 수직이나 수평으로 인접한 칸에 말을 놓아야 합니다.
3) '''삼각형'''을 놓으면 다음 플레이어는 삼각형의 방향에 맞게 말을 놓아야 합니다. 삼각형을 놓은 플레이어가 방향을 결정하며, 이 방향은 나중에 바꿀 수 없습니다.
게임판의 테두리에서 삼각형이 게임판 바깥을 향하도록 놓을 수는 없습니다.
4) '''원통'''을 놓으면 다음 플레이어는 같은 칸에 말을 놓아야 합니다.
게임을 시작할 때는 하얀색 플레이어가 빈칸 하나에 말을 놓습니다.
이미 말이 1개나 2개 있는 곳에도 배치 규칙을 지킨다면 같은 칸에 말을 놓을 수 있습니다.
위의 규칙에 따라 말을 놓을 수 없다면 게임판의 빈칸 하나를 골라 말을 놓아야 합니다.
빈칸에 둘 수도 없다면 게임이 즉시 끝납니다.
누군가가 한 칸에 3번째 말을 놓아 탑을 완성시키면 완성된 탑에 자기 말의 수가 더 많은 플레이어가 탑을 차지합니다.
== 게임 종료 ==
완성된 탑 3개를 차지하면 즉시 승리합니다.
아무도 탑을 차지하지 못했다면 차지한 완성된 탑의 수가 가장 많은 사람이 승리합니다.
차지한 완성된 탑의 수가 같으면 차지한 미완성인 탑 중 말이 2개 놓인 탑의 수를 먼저 비교하고, 여전히 동률이면 말이 1개 놓인 탑의 수를 비교합니다. 이번에도 동률이면 무승부입니다.
cf1ed08cd8bfb054b3916b6aca367bf44a4095c3
Gamehelpbahamataxi
0
212
1352
2021-12-01T05:28:16Z
Ufm
6353
새 문서: == 소개 == 바하마 택시는 도시의 택시 운전사가 되어 승객을 실어나르며 더 많은 수입을 얻기 위해 서로 경쟁하는 2~4인 게임입니다. == 준...
wikitext
text/x-wiki
== 소개 ==
바하마 택시는 도시의 택시 운전사가 되어 승객을 실어나르며 더 많은 수입을 얻기 위해 서로 경쟁하는 2~4인 게임입니다.
== 준비물 ==
* 게임판
* 52장의 표준 트럼프 카드 덱
* 플레이어마다 서로 구분이 가능한 말 1개씩
* 필기구
== 게임판 ==
[[File:BahamaBoard.png|300px]]
게임판에는 카드 종류에 따라 나눠진 52칸으로 구성된 도시 연결망이 그려져 있습니다.
게임판의 구역을 카드 무늬(♠, ♥, ♣, ♦)에 맞춰 넷으로 나눕니다.
게임판의 가운데에 있는 '중심가'에는 카드 숫자(A, K, Q, J...)가 적혀있습니다.
직선으로 이어져있거나 붙어있는 칸은 서로 인접한 칸입니다.
; 서로 인접한 칸 한 쌍의 예:
: 5♦, 2♠
: D♠, A♠
: A♣, K♣
; 서로 인접하지 않은 칸 한 쌍의 예:
: 3♥, 5♥
: A♠, A♣
''참고: 보드게임 아레나 이식에서는 시인성을 높이기 위해 4색 카드 덱과 4색 게임판을 사용합니다.''
== 택시 이동 ==
각자 택시 하나를 갖고 시작합니다. 택시는 게임판에 둔 말로 표시합니다. 한 칸에는 한 택시만 둘 수 있습니다.
모두 순서대로 돌아가며 차례를 진행하며, 자기 차례에는 인접한 빈칸으로 택시를 이동시켜야 합니다.
''참고: 보드게임 아레나 이식에서는 게임을 보다 동적으로 만들고 누군가가 게임을 (특히 게임 후반에) 일부러 끄는 일이 없도록 하기 위해 택시 이동이 의무화되었습니다.''
== 승객 ==
도시 주민들은 서두르지 않습니다.
X에서 Y로 이동하고 싶은 시민은 X에서 자신을 실어날라줄 택시가 올 때까지 기다리고, 택시를 타면 택시가 목적지인 Y까지 도착할 때까지 기다립니다.
승객은 딱히 택시의 경로를 주문하지 않고 운전사에게 운전을 일임합니다.
승객을 목적지에 내려주면 실제 경로나 운행 시간에 무관하게 X와 Y의 최단거리에 따라 요금을 받습니다.
택시를 타려고 하거나 택시에 탄 승객은 서로 위아래로 늘어놓은 1쌍의 카드로 표시합니다.
밑에 깔린 카드는 출발지인 X, 위에 덮인 카드는 도착지인 Y입니다.
X 칸에서 기다리는 승객의 카드는 X 무늬 구역 옆에 둡니다.
택시에 탄 승객의 카드는 승객이 탄 택시의 플레이어 앞에 둡니다.
목적지에 도착해 내린 승객의 카드는 버린 카드 더미에 버립니다.
''참고: 보드게임 아레나 이식에서는 카드를 해당 무늬 구역 옆에 두는 대신 출발지에 말을 추가하고 말과 카드에 강조 표시/툴팁을 적용했습니다.''
택시는 동시에 승객을 3명까지 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸에 승객이 있다면 승객을 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸이 승객의 목적지라면 승객을 내릴 수 있습니다.
== 게임 상황 예시 ==
[[File:Bahama_example.png]]
; 주석:
: 플레이어 A는 택시를 6♦ 칸으로 움직이고 3번째 승객을 태울 수 있습니다.
: 플레이어 A는 택시를 9♠ 칸으로 움직이고 승객 1명을 내릴 수 있습니다.
: 플레이어 B는 택시를 2♦ 칸으로 움직일 수 있지만, 이미 승객이 3명이므로 승객을 더 태울 수는 없습니다.
: 플레이어 C는 이미 다른 택시가 있는 10♦ 칸에는 갈 수 없습니다.
: <s>플레이어 C는 8♠ 칸에서 기다리고 3번째 승객을 태울 수 있습니다.</s>
: ''택시 이동에서 설명한 대로 보드게임 아레나 이식에서는 반드시 택시를 이동시켜야 하므로 플레이어 C는 8♠ 칸의 승객을 태울 수 없습니다.''
: 플레이어 D는 A♠ 칸과 인접하지 않은 A♣ 칸으로 움직일 수 없습니다.
{| class="wikitable"
|-
! 출발지
! 도착지
! 요금
|-
| 8♠
| 8♥
| 3
|-
| 10♠
| 10♣
| 4
|-
| K♣
| 10♥
| 2
|-
| 3♣
| A♦
| 5
|-
| K♦
| 9♣
| 3
|-
| 5♦
| 2♠
| 1
|-
| 2♦
| 2♥
| 7
|-
| 6♦
| 8♦
| 2
|}
== 게임의 무작위 요소 ==
게임을 시작할 때 카드 덱을 섞어 게임판 옆에 뒷면으로 두어 뽑기 더미를 만듭니다.
각자 카드 더미에서 카드를 1장씩 뽑아 시작 위치를 결정하고, 뽑은 카드는 버립니다.
그 후 1쌍의 카드를 뽑아 택시를 기다리는 승객을 결정합니다. 승객은 8명까지 뽑습니다.
누군가가 승객을 태웠을 때 카드가 남아있다면 카드를 뽑아 다음 승객을 무작위로 결정합니다.
''참고: 보드게임 아레나 이식에서는 3인 게임에서 덱의 카드 수를 짝수로 맞추기 위해 카드 1장을 버리고 시작합니다.''
== 게임의 마지막 단계 ==
뽑기 더미의 카드가 떨어지면 3번째 승객을 태울 수 없습니다. 이미 승객을 3명 태웠으면 그대로 둡니다.
''참고: 보드게임 아레나 이식에서는 이미 뽑힌 카드의 칸 테두리를 회색으로 바꿉니다. 모든 칸의 테두리가 회색이 될 때 뽑기 더미가 떨어집니다.''
택시를 기다리는 승객이 4명 이하가 되면 2번째 승객을 태울 수 없습니다. 이미 승객을 2명 태웠으면 그대로 둡니다.
아무도 택시를 기다리지 않으면 즉시 게임을 마치고 수입을 비교합니다. 택시에 남아있는 승객의 수입은 받지 못합니다.
== 저작자 표시 ==
[https://boardgamearena.com/gamepanel?game=bahamataxi 바하마 택시의 보드게임 아레나 이식]은 [https://creativecommons.org/licenses/by/4.0/deed.en CC BY 4.0] 규약에 따라 이용한 [https://bsulkowski.pl/contact/ Bartosz Sułkowski]의 [https://bsulkowski.pl/bahama-taxi/ "Bahama Taxi"] 기반 2차 저작물입니다.
9a2bd4d870c4585cea0ba385b2f5ec40680b365d
1355
1352
2021-12-01T08:05:01Z
Ufm
6353
wikitext
text/x-wiki
== 소개 ==
바하마 택시는 도시의 택시 운전사가 되어 승객을 실어나르며 더 많은 수입을 얻기 위해 서로 경쟁하는 2~4인 게임입니다.
== 준비물 ==
* 게임판
* 52장의 표준 트럼프 카드 덱
* 플레이어마다 서로 구분이 가능한 말 1개씩
* 필기구
== 게임판 ==
[[File:BahamaBoard.png|300px]]
게임판에는 카드 종류에 따라 나눠진 52칸으로 구성된 도시 연결망이 그려져 있습니다.
게임판의 구역을 카드 무늬(♠, ♥, ♣, ♦)에 맞춰 넷으로 나눕니다.
게임판의 가운데에 있는 '중심가'에는 카드 숫자(A, K, Q, J...)가 적혀있습니다.
직선으로 이어져있거나 붙어있는 칸은 서로 인접한 칸입니다.
; 서로 인접한 칸 한 쌍의 예:
: 5♦, 2♠
: Q♠, A♠
: A♣, K♣
; 서로 인접하지 않은 칸 한 쌍의 예:
: 3♥, 5♥
: A♠, A♣
''참고: 보드게임 아레나 이식에서는 시인성을 높이기 위해 4색 카드 덱과 4색 게임판을 사용합니다.''
== 택시 이동 ==
각자 택시 하나를 갖고 시작합니다. 택시는 게임판에 둔 말로 표시합니다. 한 칸에는 한 택시만 둘 수 있습니다.
모두 순서대로 돌아가며 차례를 진행하며, 자기 차례에는 인접한 빈칸으로 택시를 이동시켜야 합니다.
''참고: 보드게임 아레나 이식에서는 게임을 보다 동적으로 만들고 누군가가 게임을 (특히 게임 후반에) 일부러 끄는 일이 없도록 하기 위해 택시 이동이 의무화되었습니다.''
== 승객 ==
도시 주민들은 서두르지 않습니다.
X에서 Y로 이동하고 싶은 시민은 X에서 자신을 실어날라줄 택시가 올 때까지 기다리고, 택시를 타면 택시가 목적지인 Y까지 도착할 때까지 기다립니다.
승객은 딱히 택시의 경로를 주문하지 않고 운전사에게 운전을 일임합니다.
승객을 목적지에 내려주면 실제 경로나 운행 시간에 무관하게 X와 Y의 최단거리에 따라 요금을 받습니다.
택시를 타려고 하거나 택시에 탄 승객은 서로 위아래로 늘어놓은 1쌍의 카드로 표시합니다.
밑에 깔린 카드는 출발지인 X, 위에 덮인 카드는 도착지인 Y입니다.
X 칸에서 기다리는 승객의 카드는 X 무늬 구역 옆에 둡니다.
택시에 탄 승객의 카드는 승객이 탄 택시의 플레이어 앞에 둡니다.
목적지에 도착해 내린 승객의 카드는 버린 카드 더미에 버립니다.
''참고: 보드게임 아레나 이식에서는 카드를 해당 무늬 구역 옆에 두는 대신 출발지에 말을 추가하고 말과 카드에 강조 표시/툴팁을 적용했습니다.''
택시는 동시에 승객을 3명까지 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸에 승객이 있다면 승객을 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸이 승객의 목적지라면 승객을 내릴 수 있습니다.
== 게임 상황 예시 ==
[[File:Bahama_example.png]]
; 주석:
: 플레이어 A는 택시를 6♦ 칸으로 움직이고 3번째 승객을 태울 수 있습니다.
: 플레이어 A는 택시를 9♠ 칸으로 움직이고 승객 1명을 내릴 수 있습니다.
: 플레이어 B는 택시를 2♦ 칸으로 움직일 수 있지만, 이미 승객이 3명이므로 승객을 더 태울 수는 없습니다.
: 플레이어 C는 이미 다른 택시가 있는 10♦ 칸에는 갈 수 없습니다.
: <s>플레이어 C는 8♠ 칸에서 기다리고 3번째 승객을 태울 수 있습니다.</s>
: ''택시 이동에서 설명한 대로 보드게임 아레나 이식에서는 반드시 택시를 이동시켜야 하므로 플레이어 C는 8♠ 칸의 승객을 태울 수 없습니다.''
: 플레이어 D는 A♠ 칸과 인접하지 않은 A♣ 칸으로 움직일 수 없습니다.
{| class="wikitable"
|-
! 출발지
! 도착지
! 요금
|-
| 8♠
| 8♥
| 3
|-
| 10♠
| 10♣
| 4
|-
| K♣
| 10♥
| 2
|-
| 3♣
| A♦
| 5
|-
| K♦
| 9♣
| 3
|-
| 5♦
| 2♠
| 1
|-
| 2♦
| 2♥
| 7
|-
| 6♦
| 8♦
| 2
|}
== 게임의 무작위 요소 ==
게임을 시작할 때 카드 덱을 섞어 게임판 옆에 뒷면으로 두어 뽑기 더미를 만듭니다.
각자 카드 더미에서 카드를 1장씩 뽑아 시작 위치를 결정하고, 뽑은 카드는 버립니다.
그 후 1쌍의 카드를 뽑아 택시를 기다리는 승객을 결정합니다. 승객은 8명까지 뽑습니다.
누군가가 승객을 태웠을 때 카드가 남아있다면 카드를 뽑아 다음 승객을 무작위로 결정합니다.
''참고: 보드게임 아레나 이식에서는 3인 게임에서 덱의 카드 수를 짝수로 맞추기 위해 카드 1장을 버리고 시작합니다.''
== 게임의 마지막 단계 ==
뽑기 더미의 카드가 떨어지면 3번째 승객을 태울 수 없습니다. 이미 승객을 3명 태웠으면 그대로 둡니다.
''참고: 보드게임 아레나 이식에서는 이미 뽑힌 카드의 칸 테두리를 회색으로 바꿉니다. 모든 칸의 테두리가 회색이 될 때 뽑기 더미가 떨어집니다.''
택시를 기다리는 승객이 4명 이하가 되면 2번째 승객을 태울 수 없습니다. 이미 승객을 2명 태웠으면 그대로 둡니다.
아무도 택시를 기다리지 않으면 즉시 게임을 마치고 수입을 비교합니다. 택시에 남아있는 승객의 수입은 받지 못합니다.
== 저작자 표시 ==
[https://boardgamearena.com/gamepanel?game=bahamataxi 바하마 택시의 보드게임 아레나 이식]은 [https://creativecommons.org/licenses/by/4.0/deed.en CC BY 4.0] 규약에 따라 이용한 [https://bsulkowski.pl/contact/ Bartosz Sułkowski]의 [https://bsulkowski.pl/bahama-taxi/ "Bahama Taxi"] 기반 2차 저작물입니다.
21afccb4dbd3782a9564bf02f3cf9ca28b6469b2
1356
1355
2021-12-01T08:06:09Z
Ufm
6353
/* 승객 */
wikitext
text/x-wiki
== 소개 ==
바하마 택시는 도시의 택시 운전사가 되어 승객을 실어나르며 더 많은 수입을 얻기 위해 서로 경쟁하는 2~4인 게임입니다.
== 준비물 ==
* 게임판
* 52장의 표준 트럼프 카드 덱
* 플레이어마다 서로 구분이 가능한 말 1개씩
* 필기구
== 게임판 ==
[[File:BahamaBoard.png|300px]]
게임판에는 카드 종류에 따라 나눠진 52칸으로 구성된 도시 연결망이 그려져 있습니다.
게임판의 구역을 카드 무늬(♠, ♥, ♣, ♦)에 맞춰 넷으로 나눕니다.
게임판의 가운데에 있는 '중심가'에는 카드 숫자(A, K, Q, J...)가 적혀있습니다.
직선으로 이어져있거나 붙어있는 칸은 서로 인접한 칸입니다.
; 서로 인접한 칸 한 쌍의 예:
: 5♦, 2♠
: Q♠, A♠
: A♣, K♣
; 서로 인접하지 않은 칸 한 쌍의 예:
: 3♥, 5♥
: A♠, A♣
''참고: 보드게임 아레나 이식에서는 시인성을 높이기 위해 4색 카드 덱과 4색 게임판을 사용합니다.''
== 택시 이동 ==
각자 택시 하나를 갖고 시작합니다. 택시는 게임판에 둔 말로 표시합니다. 한 칸에는 한 택시만 둘 수 있습니다.
모두 순서대로 돌아가며 차례를 진행하며, 자기 차례에는 인접한 빈칸으로 택시를 이동시켜야 합니다.
''참고: 보드게임 아레나 이식에서는 게임을 보다 동적으로 만들고 누군가가 게임을 (특히 게임 후반에) 일부러 끄는 일이 없도록 하기 위해 택시 이동이 의무화되었습니다.''
== 승객 ==
도시 주민들은 서두르지 않습니다.
X에서 Y로 이동하고 싶은 시민은 X에서 자신을 실어날라줄 택시가 올 때까지 기다리고, 택시를 타면 택시가 목적지인 Y에 도착할 때까지 기다립니다.
승객은 딱히 택시의 경로를 주문하지 않고 운전사에게 운전을 일임합니다.
승객을 목적지에 내려주면 실제 경로나 운행 시간에 무관하게 X와 Y의 최단거리에 따라 요금을 받습니다.
택시를 타려고 하거나 택시에 탄 승객은 서로 위아래로 늘어놓은 1쌍의 카드로 표시합니다.
밑에 깔린 카드는 출발지인 X, 위에 덮인 카드는 도착지인 Y입니다.
X 칸에서 기다리는 승객의 카드는 X 무늬 구역 옆에 둡니다.
택시에 탄 승객의 카드는 승객이 탄 택시의 플레이어 앞에 둡니다.
목적지에 도착해 내린 승객의 카드는 버린 카드 더미에 버립니다.
''참고: 보드게임 아레나 이식에서는 카드를 해당 무늬 구역 옆에 두는 대신 출발지에 말을 추가하고 말과 카드에 강조 표시/툴팁을 적용했습니다.''
택시는 동시에 승객을 3명까지 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸에 승객이 있다면 승객을 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸이 승객의 목적지라면 승객을 내릴 수 있습니다.
== 게임 상황 예시 ==
[[File:Bahama_example.png]]
; 주석:
: 플레이어 A는 택시를 6♦ 칸으로 움직이고 3번째 승객을 태울 수 있습니다.
: 플레이어 A는 택시를 9♠ 칸으로 움직이고 승객 1명을 내릴 수 있습니다.
: 플레이어 B는 택시를 2♦ 칸으로 움직일 수 있지만, 이미 승객이 3명이므로 승객을 더 태울 수는 없습니다.
: 플레이어 C는 이미 다른 택시가 있는 10♦ 칸에는 갈 수 없습니다.
: <s>플레이어 C는 8♠ 칸에서 기다리고 3번째 승객을 태울 수 있습니다.</s>
: ''택시 이동에서 설명한 대로 보드게임 아레나 이식에서는 반드시 택시를 이동시켜야 하므로 플레이어 C는 8♠ 칸의 승객을 태울 수 없습니다.''
: 플레이어 D는 A♠ 칸과 인접하지 않은 A♣ 칸으로 움직일 수 없습니다.
{| class="wikitable"
|-
! 출발지
! 도착지
! 요금
|-
| 8♠
| 8♥
| 3
|-
| 10♠
| 10♣
| 4
|-
| K♣
| 10♥
| 2
|-
| 3♣
| A♦
| 5
|-
| K♦
| 9♣
| 3
|-
| 5♦
| 2♠
| 1
|-
| 2♦
| 2♥
| 7
|-
| 6♦
| 8♦
| 2
|}
== 게임의 무작위 요소 ==
게임을 시작할 때 카드 덱을 섞어 게임판 옆에 뒷면으로 두어 뽑기 더미를 만듭니다.
각자 카드 더미에서 카드를 1장씩 뽑아 시작 위치를 결정하고, 뽑은 카드는 버립니다.
그 후 1쌍의 카드를 뽑아 택시를 기다리는 승객을 결정합니다. 승객은 8명까지 뽑습니다.
누군가가 승객을 태웠을 때 카드가 남아있다면 카드를 뽑아 다음 승객을 무작위로 결정합니다.
''참고: 보드게임 아레나 이식에서는 3인 게임에서 덱의 카드 수를 짝수로 맞추기 위해 카드 1장을 버리고 시작합니다.''
== 게임의 마지막 단계 ==
뽑기 더미의 카드가 떨어지면 3번째 승객을 태울 수 없습니다. 이미 승객을 3명 태웠으면 그대로 둡니다.
''참고: 보드게임 아레나 이식에서는 이미 뽑힌 카드의 칸 테두리를 회색으로 바꿉니다. 모든 칸의 테두리가 회색이 될 때 뽑기 더미가 떨어집니다.''
택시를 기다리는 승객이 4명 이하가 되면 2번째 승객을 태울 수 없습니다. 이미 승객을 2명 태웠으면 그대로 둡니다.
아무도 택시를 기다리지 않으면 즉시 게임을 마치고 수입을 비교합니다. 택시에 남아있는 승객의 수입은 받지 못합니다.
== 저작자 표시 ==
[https://boardgamearena.com/gamepanel?game=bahamataxi 바하마 택시의 보드게임 아레나 이식]은 [https://creativecommons.org/licenses/by/4.0/deed.en CC BY 4.0] 규약에 따라 이용한 [https://bsulkowski.pl/contact/ Bartosz Sułkowski]의 [https://bsulkowski.pl/bahama-taxi/ "Bahama Taxi"] 기반 2차 저작물입니다.
48fe24a89be352ea9f0b39ea633186ebb886f1f1
1358
1356
2021-12-09T09:10:35Z
Ufm
6353
wikitext
text/x-wiki
== 소개 ==
바하마 택시는 도시의 택시 운전사가 되어 승객을 실어나르며 더 많은 수입을 얻기 위해 서로 경쟁하는 2~4인 게임입니다.
== 준비물 ==
* 게임판
* 52장의 표준 트럼프 카드 덱
* 플레이어마다 서로 구분이 가능한 말 1개씩
* 필기구
== 게임판 ==
[[File:BahamaBoard.png|300px]]
게임판에는 카드 종류에 따라 나눠진 52칸으로 구성된 도시 연결망이 그려져 있습니다.
게임판의 구역을 카드 무늬(♠, ♥, ♣, ♦)에 맞춰 넷으로 나눕니다.
게임판의 가운데에 있는 '중심가'에는 카드 숫자(A, K, Q, J...)가 적혀있습니다.
직선으로 이어져있거나 붙어있는 칸은 서로 인접한 칸입니다.
; 서로 인접한 칸 한 쌍의 예:
: 5♦, 2♠
: Q♠, A♠
: A♣, K♣
; 서로 인접하지 않은 칸 한 쌍의 예:
: 3♥, 5♥
: A♠, A♣
''참고: 보드게임 아레나 이식에서는 시인성을 높이기 위해 4색 카드 덱과 4색 게임판을 사용합니다.''
== 택시 이동 ==
각자 택시 하나를 갖고 시작합니다. 택시는 게임판에 둔 말로 표시합니다. 한 칸에는 한 택시만 둘 수 있습니다.
모두 순서대로 돌아가며 차례를 진행하며, 자기 차례에는 인접한 빈칸으로 택시를 이동시켜야 합니다.
''참고: 보드게임 아레나 이식에서는 게임을 보다 동적으로 만들고 누군가가 게임을 (특히 게임 후반에) 일부러 끄는 일이 없도록 하기 위해 택시 이동이 의무화되었습니다.''
== 승객 ==
도시 주민들은 서두르지 않습니다.
X에서 Y로 이동하고 싶은 시민은 X에서 자신을 실어날라줄 택시가 올 때까지 기다리고, 택시를 타면 택시가 목적지인 Y에 도착할 때까지 기다립니다.
승객은 딱히 택시의 경로를 주문하지 않고 운전사에게 운전을 일임합니다.
승객을 목적지에 내려주면 실제 경로나 운행 시간에 무관하게 X와 Y의 최단거리에 따라 요금을 받습니다.
택시를 타려고 하거나 택시에 탄 승객은 서로 위아래로 늘어놓은 1쌍의 카드로 표시합니다.
밑에 깔린 카드는 출발지인 X, 위에 덮인 카드는 도착지인 Y입니다.
X 칸에서 기다리는 승객의 카드는 X 무늬 구역 옆에 둡니다.
택시에 탄 승객의 카드는 승객이 탄 택시의 플레이어 앞에 둡니다.
목적지에 도착해 내린 승객의 카드는 버린 카드 더미에 버립니다.
''참고: 보드게임 아레나 이식에서는 카드를 해당 무늬 구역 옆에 두는 대신 출발지에 말을 추가하고 말과 카드에 강조 표시/툴팁을 적용했습니다.''
택시는 동시에 승객을 3명까지 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸에 승객이 있다면 승객을 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸이 승객의 목적지라면 승객을 내릴 수 있습니다.
== 게임 상황 예시 ==
[[File:Bahama_example.png]]
; 주석:
: 플레이어 A는 택시를 6♦ 칸으로 움직이고 3번째 승객을 태울 수 있습니다.
: 플레이어 A는 택시를 9♠ 칸으로 움직이고 승객 1명을 내릴 수 있습니다.
: 플레이어 B는 택시를 2♦ 칸으로 움직일 수 있지만, 이미 승객이 3명이므로 승객을 더 태울 수는 없습니다.
: 플레이어 C는 이미 다른 택시가 있는 10♦ 칸에는 갈 수 없습니다.
: <s>플레이어 C는 8♠ 칸에서 기다리고 3번째 승객을 태울 수 있습니다.</s>
: ''택시 이동에서 설명한 대로 보드게임 아레나 이식에서는 반드시 택시를 이동시켜야 하므로 플레이어 C는 8♠ 칸의 승객을 태울 수 없습니다.''
: 플레이어 D는 A♠ 칸과 인접하지 않은 A♣ 칸으로 움직일 수 없습니다.
{| class="wikitable"
|-
! 출발지
! 도착지
! 요금
|-
| 8♠
| 8♥
| 3
|-
| 10♠
| 10♣
| 4
|-
| K♣
| 10♥
| 2
|-
| 3♣
| A♦
| 5
|-
| K♦
| 9♣
| 3
|-
| 5♦
| 2♠
| 1
|-
| 2♦
| 2♥
| 7
|-
| 6♦
| 8♦
| 2
|}
== 게임의 무작위 요소 ==
게임을 시작할 때 카드 덱을 섞어 게임판 옆에 뒷면으로 두어 뽑기 더미를 만듭니다.
각자 카드 더미에서 카드를 1장씩 뽑아 시작 위치를 결정하고, 뽑은 카드는 버립니다.
그 후 1쌍의 카드를 뽑아 택시를 기다리는 승객을 결정합니다. 승객은 8명까지 뽑습니다.
누군가가 승객을 태웠을 때 카드가 남아있다면 카드를 뽑아 다음 승객을 무작위로 결정합니다.
''참고: 보드게임 아레나 이식에서는 3인 게임에서 덱의 카드 수를 짝수로 맞추기 위해 카드 1장을 버리고 시작합니다.''
== 게임의 마지막 단계 ==
뽑기 더미의 카드가 떨어지면 3번째 승객을 태울 수 없습니다. 이미 승객을 3명 태웠으면 그대로 둡니다.
''참고: 보드게임 아레나 이식에서는 이미 뽑힌 카드의 칸 테두리를 회색으로 바꿉니다. 모든 칸의 테두리가 회색이 될 때 뽑기 더미가 떨어집니다.''
택시를 기다리는 승객이 4명 이하가 되면 2번째 승객을 태울 수 없습니다. 이미 승객을 2명 태웠으면 그대로 둡니다.
아무도 택시를 기다리지 않으면 즉시 게임을 마치고 수입을 비교합니다. 택시에 남아있는 승객의 수입은 받지 못합니다.
''참고: 택시를 기다리는 승객이 1명일 때 택시에 승객이 아무도 남아있지 않다면 게임이 자동으로 끝납니다.''
''마지막 승객은 태운 뒤에 내릴 수 없으므로 게임이 일찍 종료되어도 결과는 바뀌지 않습니다.''
== 변형규칙 ==
BGA 이식에서는 원래 규칙에 포함되지 않은 변형규칙을 지원합니다.
'''기본 옵션은 볼드체로 표기했습니다.'''
=== 교대 근무 ===
* '''아니요''': 각자 빈 택시로 게임을 시작합니다.
* 예: 각자 승객이 꽉 찬 택시로 게임을 시작합니다.
== 저작자 표시 ==
[https://boardgamearena.com/gamepanel?game=bahamataxi 바하마 택시의 보드게임 아레나 이식과 변형규칙]은 [https://creativecommons.org/licenses/by/4.0/deed.en CC BY 4.0] 규약에 따라 이용한 [https://bsulkowski.pl/contact/ Bartosz Sułkowski]의 [https://bsulkowski.pl/bahama-taxi/ "Bahama Taxi"] 기반 2차 저작물입니다.
152aa7c1727f76102dedbd667b4739a29d161b52
1359
1358
2021-12-15T05:52:07Z
Ufm
6353
/* 변형규칙 */
wikitext
text/x-wiki
== 소개 ==
바하마 택시는 도시의 택시 운전사가 되어 승객을 실어나르며 더 많은 수입을 얻기 위해 서로 경쟁하는 2~4인 게임입니다.
== 준비물 ==
* 게임판
* 52장의 표준 트럼프 카드 덱
* 플레이어마다 서로 구분이 가능한 말 1개씩
* 필기구
== 게임판 ==
[[File:BahamaBoard.png|300px]]
게임판에는 카드 종류에 따라 나눠진 52칸으로 구성된 도시 연결망이 그려져 있습니다.
게임판의 구역을 카드 무늬(♠, ♥, ♣, ♦)에 맞춰 넷으로 나눕니다.
게임판의 가운데에 있는 '중심가'에는 카드 숫자(A, K, Q, J...)가 적혀있습니다.
직선으로 이어져있거나 붙어있는 칸은 서로 인접한 칸입니다.
; 서로 인접한 칸 한 쌍의 예:
: 5♦, 2♠
: Q♠, A♠
: A♣, K♣
; 서로 인접하지 않은 칸 한 쌍의 예:
: 3♥, 5♥
: A♠, A♣
''참고: 보드게임 아레나 이식에서는 시인성을 높이기 위해 4색 카드 덱과 4색 게임판을 사용합니다.''
== 택시 이동 ==
각자 택시 하나를 갖고 시작합니다. 택시는 게임판에 둔 말로 표시합니다. 한 칸에는 한 택시만 둘 수 있습니다.
모두 순서대로 돌아가며 차례를 진행하며, 자기 차례에는 인접한 빈칸으로 택시를 이동시켜야 합니다.
''참고: 보드게임 아레나 이식에서는 게임을 보다 동적으로 만들고 누군가가 게임을 (특히 게임 후반에) 일부러 끄는 일이 없도록 하기 위해 택시 이동이 의무화되었습니다.''
== 승객 ==
도시 주민들은 서두르지 않습니다.
X에서 Y로 이동하고 싶은 시민은 X에서 자신을 실어날라줄 택시가 올 때까지 기다리고, 택시를 타면 택시가 목적지인 Y에 도착할 때까지 기다립니다.
승객은 딱히 택시의 경로를 주문하지 않고 운전사에게 운전을 일임합니다.
승객을 목적지에 내려주면 실제 경로나 운행 시간에 무관하게 X와 Y의 최단거리에 따라 요금을 받습니다.
택시를 타려고 하거나 택시에 탄 승객은 서로 위아래로 늘어놓은 1쌍의 카드로 표시합니다.
밑에 깔린 카드는 출발지인 X, 위에 덮인 카드는 도착지인 Y입니다.
X 칸에서 기다리는 승객의 카드는 X 무늬 구역 옆에 둡니다.
택시에 탄 승객의 카드는 승객이 탄 택시의 플레이어 앞에 둡니다.
목적지에 도착해 내린 승객의 카드는 버린 카드 더미에 버립니다.
''참고: 보드게임 아레나 이식에서는 카드를 해당 무늬 구역 옆에 두는 대신 출발지에 말을 추가하고 말과 카드에 강조 표시/툴팁을 적용했습니다.''
택시는 동시에 승객을 3명까지 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸에 승객이 있다면 승객을 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸이 승객의 목적지라면 승객을 내릴 수 있습니다.
== 게임 상황 예시 ==
[[File:Bahama_example.png]]
; 주석:
: 플레이어 A는 택시를 6♦ 칸으로 움직이고 3번째 승객을 태울 수 있습니다.
: 플레이어 A는 택시를 9♠ 칸으로 움직이고 승객 1명을 내릴 수 있습니다.
: 플레이어 B는 택시를 2♦ 칸으로 움직일 수 있지만, 이미 승객이 3명이므로 승객을 더 태울 수는 없습니다.
: 플레이어 C는 이미 다른 택시가 있는 10♦ 칸에는 갈 수 없습니다.
: <s>플레이어 C는 8♠ 칸에서 기다리고 3번째 승객을 태울 수 있습니다.</s>
: ''택시 이동에서 설명한 대로 보드게임 아레나 이식에서는 반드시 택시를 이동시켜야 하므로 플레이어 C는 8♠ 칸의 승객을 태울 수 없습니다.''
: 플레이어 D는 A♠ 칸과 인접하지 않은 A♣ 칸으로 움직일 수 없습니다.
{| class="wikitable"
|-
! 출발지
! 도착지
! 요금
|-
| 8♠
| 8♥
| 3
|-
| 10♠
| 10♣
| 4
|-
| K♣
| 10♥
| 2
|-
| 3♣
| A♦
| 5
|-
| K♦
| 9♣
| 3
|-
| 5♦
| 2♠
| 1
|-
| 2♦
| 2♥
| 7
|-
| 6♦
| 8♦
| 2
|}
== 게임의 무작위 요소 ==
게임을 시작할 때 카드 덱을 섞어 게임판 옆에 뒷면으로 두어 뽑기 더미를 만듭니다.
각자 카드 더미에서 카드를 1장씩 뽑아 시작 위치를 결정하고, 뽑은 카드는 버립니다.
그 후 1쌍의 카드를 뽑아 택시를 기다리는 승객을 결정합니다. 승객은 8명까지 뽑습니다.
누군가가 승객을 태웠을 때 카드가 남아있다면 카드를 뽑아 다음 승객을 무작위로 결정합니다.
''참고: 보드게임 아레나 이식에서는 3인 게임에서 덱의 카드 수를 짝수로 맞추기 위해 카드 1장을 버리고 시작합니다.''
== 게임의 마지막 단계 ==
뽑기 더미의 카드가 떨어지면 3번째 승객을 태울 수 없습니다. 이미 승객을 3명 태웠으면 그대로 둡니다.
''참고: 보드게임 아레나 이식에서는 이미 뽑힌 카드의 칸 테두리를 회색으로 바꿉니다. 모든 칸의 테두리가 회색이 될 때 뽑기 더미가 떨어집니다.''
택시를 기다리는 승객이 4명 이하가 되면 2번째 승객을 태울 수 없습니다. 이미 승객을 2명 태웠으면 그대로 둡니다.
아무도 택시를 기다리지 않으면 즉시 게임을 마치고 수입을 비교합니다. 택시에 남아있는 승객의 수입은 받지 못합니다.
''참고: 택시를 기다리는 승객이 1명일 때 택시에 승객이 아무도 남아있지 않다면 게임이 자동으로 끝납니다.''
''마지막 승객은 태운 뒤에 내릴 수 없으므로 게임이 일찍 종료되어도 결과는 바뀌지 않습니다.''
== 변형규칙 ==
BGA 이식에서는 원래 규칙에 포함되지 않은 변형규칙을 지원합니다.
'''기본 옵션은 볼드체로 표기했습니다.'''
=== 교대 근무 ===
* '''아니요''': 각자 빈 택시로 게임을 시작합니다.
* 예: 각자 승객이 꽉 찬 택시로 게임을 시작합니다.
=== 이동 전에 승객 태우기 ===
* '''아니요''': 택시가 이동하기 전에는 같은 칸의 승객을 태울 수 없습니다.
* 예: 택시가 이동하기 전에 같은 칸의 승객을 태울 수 있습니다. 카드 더미가 모두 떨어지면 이 규칙을 적용하지 않습니다.
=== 더 빠른 이동 ===
* '''아니요''': 택시는 한 차례에 한 번만 움직입니다. 택시는 반드시 이동해야 합니다.
* 빠름: 택시는 한 차례에 2번까지 이동할 수 있습니다. 1번째/2번째 마감시간 경고가 표시되면 모든 택시의 이동 한도가 1번/2번 늘어납니다.
* 더 빠름: 택시는 한 차례에 3번까지 이동할 수 있습니다. 1번째/2번째 마감시간 경고가 표시되면 모든 택시의 이동 한도가 2번/4번 늘어납니다.
택시 이동은 한 차례에 5번까지 초기화할 수 있습니다.
모든 규칙에서 택시는 최소 1번은 이동해야 하며, 출발점으로 돌아올 (또는 출발점에 머무를) 수는 없습니다.
('이동 전에 승객 태우기' 변형규칙을 사용하지 않는다면) 승객을 태우거나 내리려면 먼저 이동을 마쳐야 합니다.
=== 5~8인 변형규칙 ===
5~8인 게임에서는 카드 덱 2개를 사용합니다.
* '이동 전에 승객 태우기' 변형규칙을 선택해야 합니다.
* 택시에 충분한 빈 자리가 있고 같은 칸에 승객이 2명 있다면 승객을 0~2명 태울 수 있습니다.
* 택시에 탄 승객 2명의 목적지가 같다면 두 승객을 동시에 내리고 동시에 요금을 받습니다.
* 승객을 정하는 카드를 뽑을 때 똑같은 카드 1쌍이 뽑히면, 즉시 뽑힌 카드를 버리고 서로 다른 카드 1쌍으로 승객이 정해지거나 카드 더미가 모두 떨어질 때까지 새 카드를 뽑습니다.
== 저작자 표시 ==
[https://boardgamearena.com/gamepanel?game=bahamataxi 바하마 택시의 보드게임 아레나 이식과 변형규칙]은 [https://creativecommons.org/licenses/by/4.0/deed.en CC BY 4.0] 규약에 따라 이용한 [https://bsulkowski.pl/contact/ Bartosz Sułkowski]의 [https://bsulkowski.pl/bahama-taxi/ "Bahama Taxi"] 기반 2차 저작물입니다.
5ce351b24ca664a6fce66944049e9a5f929d991d
1360
1359
2021-12-17T08:38:10Z
Ufm
6353
/* 5~8인 변형규칙 */
wikitext
text/x-wiki
== 소개 ==
바하마 택시는 도시의 택시 운전사가 되어 승객을 실어나르며 더 많은 수입을 얻기 위해 서로 경쟁하는 2~4인 게임입니다.
== 준비물 ==
* 게임판
* 52장의 표준 트럼프 카드 덱
* 플레이어마다 서로 구분이 가능한 말 1개씩
* 필기구
== 게임판 ==
[[File:BahamaBoard.png|300px]]
게임판에는 카드 종류에 따라 나눠진 52칸으로 구성된 도시 연결망이 그려져 있습니다.
게임판의 구역을 카드 무늬(♠, ♥, ♣, ♦)에 맞춰 넷으로 나눕니다.
게임판의 가운데에 있는 '중심가'에는 카드 숫자(A, K, Q, J...)가 적혀있습니다.
직선으로 이어져있거나 붙어있는 칸은 서로 인접한 칸입니다.
; 서로 인접한 칸 한 쌍의 예:
: 5♦, 2♠
: Q♠, A♠
: A♣, K♣
; 서로 인접하지 않은 칸 한 쌍의 예:
: 3♥, 5♥
: A♠, A♣
''참고: 보드게임 아레나 이식에서는 시인성을 높이기 위해 4색 카드 덱과 4색 게임판을 사용합니다.''
== 택시 이동 ==
각자 택시 하나를 갖고 시작합니다. 택시는 게임판에 둔 말로 표시합니다. 한 칸에는 한 택시만 둘 수 있습니다.
모두 순서대로 돌아가며 차례를 진행하며, 자기 차례에는 인접한 빈칸으로 택시를 이동시켜야 합니다.
''참고: 보드게임 아레나 이식에서는 게임을 보다 동적으로 만들고 누군가가 게임을 (특히 게임 후반에) 일부러 끄는 일이 없도록 하기 위해 택시 이동이 의무화되었습니다.''
== 승객 ==
도시 주민들은 서두르지 않습니다.
X에서 Y로 이동하고 싶은 시민은 X에서 자신을 실어날라줄 택시가 올 때까지 기다리고, 택시를 타면 택시가 목적지인 Y에 도착할 때까지 기다립니다.
승객은 딱히 택시의 경로를 주문하지 않고 운전사에게 운전을 일임합니다.
승객을 목적지에 내려주면 실제 경로나 운행 시간에 무관하게 X와 Y의 최단거리에 따라 요금을 받습니다.
택시를 타려고 하거나 택시에 탄 승객은 서로 위아래로 늘어놓은 1쌍의 카드로 표시합니다.
밑에 깔린 카드는 출발지인 X, 위에 덮인 카드는 도착지인 Y입니다.
X 칸에서 기다리는 승객의 카드는 X 무늬 구역 옆에 둡니다.
택시에 탄 승객의 카드는 승객이 탄 택시의 플레이어 앞에 둡니다.
목적지에 도착해 내린 승객의 카드는 버린 카드 더미에 버립니다.
''참고: 보드게임 아레나 이식에서는 카드를 해당 무늬 구역 옆에 두는 대신 출발지에 말을 추가하고 말과 카드에 강조 표시/툴팁을 적용했습니다.''
택시는 동시에 승객을 3명까지 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸에 승객이 있다면 승객을 태울 수 있습니다.
자기 차례가 끝날 때 택시가 있는 칸이 승객의 목적지라면 승객을 내릴 수 있습니다.
== 게임 상황 예시 ==
[[File:Bahama_example.png]]
; 주석:
: 플레이어 A는 택시를 6♦ 칸으로 움직이고 3번째 승객을 태울 수 있습니다.
: 플레이어 A는 택시를 9♠ 칸으로 움직이고 승객 1명을 내릴 수 있습니다.
: 플레이어 B는 택시를 2♦ 칸으로 움직일 수 있지만, 이미 승객이 3명이므로 승객을 더 태울 수는 없습니다.
: 플레이어 C는 이미 다른 택시가 있는 10♦ 칸에는 갈 수 없습니다.
: <s>플레이어 C는 8♠ 칸에서 기다리고 3번째 승객을 태울 수 있습니다.</s>
: ''택시 이동에서 설명한 대로 보드게임 아레나 이식에서는 반드시 택시를 이동시켜야 하므로 플레이어 C는 8♠ 칸의 승객을 태울 수 없습니다.''
: 플레이어 D는 A♠ 칸과 인접하지 않은 A♣ 칸으로 움직일 수 없습니다.
{| class="wikitable"
|-
! 출발지
! 도착지
! 요금
|-
| 8♠
| 8♥
| 3
|-
| 10♠
| 10♣
| 4
|-
| K♣
| 10♥
| 2
|-
| 3♣
| A♦
| 5
|-
| K♦
| 9♣
| 3
|-
| 5♦
| 2♠
| 1
|-
| 2♦
| 2♥
| 7
|-
| 6♦
| 8♦
| 2
|}
== 게임의 무작위 요소 ==
게임을 시작할 때 카드 덱을 섞어 게임판 옆에 뒷면으로 두어 뽑기 더미를 만듭니다.
각자 카드 더미에서 카드를 1장씩 뽑아 시작 위치를 결정하고, 뽑은 카드는 버립니다.
그 후 1쌍의 카드를 뽑아 택시를 기다리는 승객을 결정합니다. 승객은 8명까지 뽑습니다.
누군가가 승객을 태웠을 때 카드가 남아있다면 카드를 뽑아 다음 승객을 무작위로 결정합니다.
''참고: 보드게임 아레나 이식에서는 3인 게임에서 덱의 카드 수를 짝수로 맞추기 위해 카드 1장을 버리고 시작합니다.''
== 게임의 마지막 단계 ==
뽑기 더미의 카드가 떨어지면 3번째 승객을 태울 수 없습니다. 이미 승객을 3명 태웠으면 그대로 둡니다.
''참고: 보드게임 아레나 이식에서는 이미 뽑힌 카드의 칸 테두리를 회색으로 바꿉니다. 모든 칸의 테두리가 회색이 될 때 뽑기 더미가 떨어집니다.''
택시를 기다리는 승객이 4명 이하가 되면 2번째 승객을 태울 수 없습니다. 이미 승객을 2명 태웠으면 그대로 둡니다.
아무도 택시를 기다리지 않으면 즉시 게임을 마치고 수입을 비교합니다. 택시에 남아있는 승객의 수입은 받지 못합니다.
''참고: 택시를 기다리는 승객이 1명일 때 택시에 승객이 아무도 남아있지 않다면 게임이 자동으로 끝납니다.''
''마지막 승객은 태운 뒤에 내릴 수 없으므로 게임이 일찍 종료되어도 결과는 바뀌지 않습니다.''
== 변형규칙 ==
BGA 이식에서는 원래 규칙에 포함되지 않은 변형규칙을 지원합니다.
'''기본 옵션은 볼드체로 표기했습니다.'''
=== 교대 근무 ===
* '''아니요''': 각자 빈 택시로 게임을 시작합니다.
* 예: 각자 승객이 꽉 찬 택시로 게임을 시작합니다.
=== 이동 전에 승객 태우기 ===
* '''아니요''': 택시가 이동하기 전에는 같은 칸의 승객을 태울 수 없습니다.
* 예: 택시가 이동하기 전에 같은 칸의 승객을 태울 수 있습니다. 카드 더미가 모두 떨어지면 이 규칙을 적용하지 않습니다.
=== 더 빠른 이동 ===
* '''아니요''': 택시는 한 차례에 한 번만 움직입니다. 택시는 반드시 이동해야 합니다.
* 빠름: 택시는 한 차례에 2번까지 이동할 수 있습니다. 1번째/2번째 마감시간 경고가 표시되면 모든 택시의 이동 한도가 1번/2번 늘어납니다.
* 더 빠름: 택시는 한 차례에 3번까지 이동할 수 있습니다. 1번째/2번째 마감시간 경고가 표시되면 모든 택시의 이동 한도가 2번/4번 늘어납니다.
택시 이동은 한 차례에 5번까지 초기화할 수 있습니다.
모든 규칙에서 택시는 최소 1번은 이동해야 하며, 출발점으로 돌아올 (또는 출발점에 머무를) 수는 없습니다.
('이동 전에 승객 태우기' 변형규칙을 사용하지 않는다면) 승객을 태우거나 내리려면 먼저 이동을 마쳐야 합니다.
=== 5~8인 변형규칙 ===
5~8인 게임에서는 카드 덱 2개를 사용합니다.
* '이동 전에 승객 태우기' 변형규칙을 선택해야 합니다.
* 게임을 시작할 때 다른 사람의 시작 위치와 똑같은 카드를 뽑으면 뽑은 카드를 옆으로 치워두고 빈칸을 표시하는 카드가 나올 때까지 새 카드를 뽑은 뒤, 자리가 정해지면 치운 카드를 카드 더미로 섞어넣습니다.
* 택시에 충분한 빈 자리가 있고 같은 칸에 승객이 2명 있다면 승객을 0~2명 태울 수 있습니다.
* 택시에 탄 승객 2명의 목적지가 같다면 두 승객을 동시에 내리고 동시에 요금을 받습니다.
* 승객을 정하는 카드를 뽑을 때 똑같은 카드 1쌍이 뽑히면, 즉시 뽑힌 카드를 버리고 서로 다른 카드 1쌍으로 승객이 정해지거나 카드 더미가 모두 떨어질 때까지 새 카드를 뽑습니다.
== 저작자 표시 ==
[https://boardgamearena.com/gamepanel?game=bahamataxi 바하마 택시의 보드게임 아레나 이식과 변형규칙]은 [https://creativecommons.org/licenses/by/4.0/deed.en CC BY 4.0] 규약에 따라 이용한 [https://bsulkowski.pl/contact/ Bartosz Sułkowski]의 [https://bsulkowski.pl/bahama-taxi/ "Bahama Taxi"] 기반 2차 저작물입니다.
372b43acf7a871314ca397785926f632141b9e5e
파일:BahamaBoard.png
6
213
1353
2021-12-01T05:29:39Z
Ufm
6353
Original image is from: https://bsulkowski.pl/bahama-taxi/
wikitext
text/x-wiki
== 파일의 설명 ==
Original image is from: https://bsulkowski.pl/bahama-taxi/
0d9b1c9efcea1a1b2cbfa388911d44788b96b2a5
파일:Bahama example.png
6
214
1354
2021-12-01T05:34:56Z
Ufm
6353
From: https://bsulkowski.pl/bahama-taxi/
wikitext
text/x-wiki
== 파일의 설명 ==
From: https://bsulkowski.pl/bahama-taxi/
c59b03e5e99bad1b2e647bed1f617cde68dfb82c
Gamehelppyrgos
0
211
1357
1351
2021-12-08T03:59:14Z
Ufm
6353
wikitext
text/x-wiki
== 구성품 ==
* 4x4 격자 게임판
* 2색의 말 15개씩 (사각형 말 5개, 삼각형 말 5개, 원통 말 5개)
== 게임 컨셉 ==
피르가는 간단한 2인 추상전략게임입니다.
플레이어는 탑을 짓는 건축가가 됩니다. 자기가 놓는 말로 다음에 상대가 어디에 말을 놓을지 결정합니다. 먼저 탑 3개를 차지하면 승리합니다.
== 준비 ==
각자 색깔을 결정하고 자기 앞에 자기 색깔의 말 15개를 둡니다.
== 게임 방식 ==
자기 차례에는 아래의 규칙에 따라 자기 말 하나를 골라 놓습니다.
1) 한 칸에는 색깔에 무관하게 삼각형, 사각형, 원통 하나씩을 배치할 수 있습니다. 말이 칸에 놓인 순서는 게임에 영향을 미치지 않습니다.
2) '''사각형'''을 놓으면 다음 플레이어는 수직이나 수평으로 인접한 칸에 말을 놓아야 합니다.
3) '''삼각형'''을 놓으면 다음 플레이어는 삼각형의 방향에 맞게 말을 놓아야 합니다. 삼각형을 놓은 플레이어가 방향을 결정하며, 이 방향은 나중에 바꿀 수 없습니다.
게임판의 테두리에서 삼각형이 게임판 바깥을 향하도록 놓을 수는 없습니다.
4) '''원통'''을 놓으면 다음 플레이어는 같은 칸에 말을 놓아야 합니다.
게임을 시작할 때는 하얀색 플레이어가 빈칸 하나에 말을 놓습니다.
이미 말이 1개나 2개 있는 곳에도 배치 규칙을 지킨다면 같은 칸에 말을 놓을 수 있습니다.
위의 규칙에 따라 말을 놓을 수 없다면 게임판의 빈칸 하나를 골라 말을 놓아야 합니다.
빈칸에 둘 수도 없다면 게임이 즉시 끝납니다.
누군가가 한 칸에 3번째 말을 놓아 탑을 완성시키면 완성된 탑에 자기 말의 수가 더 많은 플레이어가 탑을 차지합니다.
== 게임 종료 ==
완성된 탑 3개를 차지하면 즉시 승리합니다.
아무도 탑을 차지하지 못했다면 차지한 완성된 탑의 수가 가장 많은 사람이 승리합니다.
차지한 완성된 탑의 수가 같으면 차지한 미완성인 탑 중 말이 2개 놓인 탑의 수를 먼저 비교하고, 여전히 동률이면 말이 1개 놓인 탑의 수를 비교합니다. 이번에도 동률이면 무승부입니다.
75e311042841577b9fd0e9079b6c2d48dd85d779
Gamehelpcubirds
0
182
1361
1238
2021-12-20T14:18:58Z
Cu 29
7771
오타수정
wikitext
text/x-wiki
[모아보새 - Cubirds]
이 게임의 목적은 7가지의 다른 종류의 카드를 1장 이상씩 모으거나, 2가지 종류의 카드를 3장 이상 모으는 것 입니다.
A game plays in several rounds. At the beginning of each round, each player starts with 8 cards in their hand and there are 4 rows with three cards faceup at the center of the table. The game starts with the dealer and go clockwise. Also, each player starts with a bird card, faceup, in front of them, which represents the first Bird in their collection.
게임은 여러 라운드로 진행됩니다. 각각의 라운드의 처음에, 각각의 플레이어는 8장의 카드를 가지고 시작합니다. 테이블의 중앙에는 3장의 카드씩 4 줄이 놓여 있습니다. 게임은 선부터 시계방향으로 진행됩니다. 또한, 각각의 플레이어는 한 장의 새카드를 앞면으로 두는데, 그것은 첫번째 새의 종류의 묶음을 나타냅니다.
Turn of a player - On their turn, a player must lay one or more birds from their hand. All the birds of the chosen specie that player have in their hand must be played. The player lays these birds (next to each other) on the left or the right side of one of the 4 rows at the center of the table. When a player places a bird in a row that already has one or more Birds of that species, the player must take all the cards between these birds into their hand. After taking the surrounded cards, remaining birds are put together and new cards are added (placed on the left or the right) from the draw pile to this row until there are two different species in it.
플레이어의 턴 - 플레이어는 손에서 한개나 그 이상의 카드를 내려놓아야 합니다. 손안에 가지고 있는 선택된 종류의 모든 새들은 내려놓아져야 합니다. 플레이어는 이러한 새들을 (각자의 옆에) 테이블 가운데에 있는 4줄의 카드의 왼쪽이나 오른쪽에 놓습니다. 한 플레이어가 한개나 그 이상의 개수가 이미 있는 종류의 줄에 새를 내려놓으면, 그 플레이어는 손안에 그 카드를 모두 가져가야 합니다. 주변의 카드를 가져간 후에, 남아있는 새들은 같이 놓여지고, 2가지의 다른 종류의 새카드가 놓여질 때까지 덱에서 새로운 카드가 추가됩니다. (왼쪽이나 오른쪽에 놓여져서)
If no cards were surrounded by birds of the same species, the player can’t take cards from the center of the table but they have the option to take two first cards from the draw pile to add them to their hand.
만약에 아무 카드도 같은 종의 새에 의해서 둘려쌓여지지 않는다면, 그 플레이어는 테이블의 가운데에서 카드를 가지올수 없지만, 덱에서 손에 추가할 두가지 첫번째 카드들을 가져갈 선택사항을 가집니다.
Complete a flock (optional) – a series of birds of the same species (a flock) that the player hold in their hand may be revealed to add one or two of this cards to their collection.
하나의 새 무리를 완성하기 (선택적) - 플레이어가 손에 가지고 있는 같은 종류의 새들의 묶음(새 무리)는 그들의 묶음에 한개 또는 두개 이상이 추가될 것입니다.
Each card has two numbers, the lower representing the number stated for the small flock and the higher representing the number stated for the big Flock. When the number of revealed cards is higher or equal to:
각각의 카드는 2개의 숫자를 가지고 있습니다. 낮은 숫자는 작은 새 무리에 대해 쓰여진 숫자를 나타내고, 더 높은 숫자는 큰 새 무리에 대해 쓰여진 숫자를 나타냅니다. 드러난 카드들의 숫자가 더 높거나 동등하다면 :
- the small flock, the player adds one of the revealed cards to their collection;
- 작은 새 무리의 플레이어는 드러난 카드들 중에 하나를 그들의 묶음에 더합니다.
- the big flock, the player adds two of the revealed cards to their collection.
-큰 무리의 새 플레이어는 드러난 카드들 중에서 2개를 그들의 묶음에 더합니다.
The remaining cards are placed into the discard pile. On their turn, a player can only complete a single Flock.
남은 카드들은 버려지는 더미에 놓여집니다. 한 플레이어는 턴에 하나의 새 무리만 완성할 수 있습니다.
End of a round - A round ends when one of the players has no cards left in their hand. The remaining cards that players have in their hand go to the discard pile. The cards laid in rows at the center of the table remain in place. The player who ended the round becomes the new dealer.
라운드의 끝 - 손에 카드가 남아 있지 않는 플레이어가 있다면 라운드가 끝납니다. 손에 남은 카드들은 버려지는 더미에 놓어집니다. 그 카드들은 중앙의 줄에 놓여집니다. 라운드를 끝낸 플레이어는 새로운 선이 됩니다.
End of the game – if a player completes the objective or if it is impossible to deal 8 cards to each player (even with the discard pile), the game ends immediately. In the second case, the player with the most bird cards in their collection wins the game.
게임의 종료 - 만약 한 플레이어가 목표를 달성하거나, 8개의 카드를 각각의 플레이어들에게 주는것이 불가능하다면 (버려진 카드 더미들을 포함하여), 게임이 즉시 끝납니다. 두번째 상황에서, 가장 많은 새 카드를 가진 사람이 승리합니다.
7d2bcfa04e5d21c96de30e65c9385383ae856cb6
Gamehelpsechsnimmt
0
171
1362
1225
2021-12-29T07:46:53Z
Strongberries
7784
wikitext
text/x-wiki
=젝스님트!=
이 게임의 기본적인 목표는 카드를 가져가지 않고, 다른 플레이어로 하여금 갖고 가게 하는 것입니다. 모든 플레이어는 66포인트에서 시작합니다. 여기서 카드 위에 그려진 소머리 하나 당 1점씩 감점됩니다. 만일 모든 점수를 잃는 플레이어가 나오게 된다면, 해당 라운드에서 게임은 끝나게 되고, 가장 많은 포인트가 남은 사람이 승리하게 됩니다.
==게임방법==
모든 플레이어는 10장의 카드를 갖고 시작합니다. 라운드 시작 시 네 장의 카드는 테이블에 4열로 놓여집니다. 모든 플레이어는 각자 보이지 않게 카드를 한 장 고릅니다. 그리고 모두 골랐다면, 동시에 공개합니다. 카드가 공개되었다면, 카드가 놓이기 시작합니다. 가장 낮은 숫자부터 놓이기 시작합니다. 놓이는 규칙은 (Normal 기준으로) 다음과 같습니다. ('''카드 놓기'''를 참조하세요.)
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드는 왼쪽부터 순서대로 놓아진다. 즉, 그 줄의 카드보다 작은 수의 카드는 놓이지 않는다.
게임을 진행할수록, 각 열은 카드로 채워질 것입니다. 5장이 해당 열의 최대 갯수입니다. 만약 누군가가 해당 열의 여섯번째의 카드를 놓았다면, 그 열의 카드를 모두 벌점으로 가져가게 됩니다. 이때, 카드 위의 소머리 숫자만큼 포인트가 차감됩니다. 해당 플레이어가 놓았던 마지막 카드(여섯번 째 카드)가 해당 열의 첫 숫자로 진행됩니다.
만약 누군가가 모든 숫자들보다 낮은 숫자를 놓았다면 (즉, 카드를 놓을 수 있는 열이 없는 경우), 한 열을 선택하고 벌점으로 가져간 후, 자신이 놓을 카드를 그 열의 시작하는 카드로 놓습니다.
===소머리===
각 카드는 소머리가 있습니다. 이것은 해당 카드의 벌점을 나타냅니다.
5로 끝나는 카드는 벌점 2점, 0으로 끝나는 카드는 벌점 3점, 11의 배수는 벌점 5점, 55는 벌점 7점이며, 나머지는 모두 벌점 1점입니다.
===라운드 끝내기===
라운드가 끝나면, 아무도 0점 이하로 떨어지지 않았다면, 새로운 라운드로 넘어갑니다. 만약 누군가에 점수가 0점 이하라면, 그 즉시 게임이 끝나고 가장 많은 포인트가 남은 사람이 이깁니다.
==변경 가능 규칙==
===카드 세트===
Normal : 무조건 1~104까지의 카드를 사용합니다. 이에 따라 사용되지 않는 카드는 공개되지 않습니다.
Tactics : 플레이어 수에 따라 사용하는 카드의 수가 바뀝니다. 사용되지 않는 카드가 없도록 카드 수가 조정되며, 이에 따라 숫자의 범위는 1~(인원수*10+4)가 됩니다. 이 방식은 Normal에 비해 다른 전략과 카드 카운팅의 중요성이 커집니다.
Logic : Tactics와 동일하게 카드 장수를 조절하나, 카드 배분을 랜덤이 아닌 1장씩 가져가면서 덱을 만듭니다. 플레이 시간은 길어질 것이나, 운의 요소를 거의 배제할 수 있다는 점이 특이점입니다.
===카드 놓기===
Normal : 게임 방법에 적힌 그대로, 아래와 같이 진행합니다 :
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드는 왼쪽부터 순서대로 놓아진다. 즉, 그 줄의 카드보다 작은 수의 카드는 놓이지 않는다.
Professional : 게임 방법과 다르게, 아래와 같이 진행합니다 :
1. 카드는 항상 오름차순으로 놓인다.
2. 카드는 항상 편차가 작은 숫자 옆에 놓인다.
3. 카드의 방향은 제한이 없다. 즉, 편차가 더 작다면 줄의 맨 왼쪽에 놓아질수도 있다.
cef6b44532d47d11d5899d7eea55c2ebf5493e18
Gamehelpfruitpicking
0
215
1363
2022-01-05T07:32:42Z
Ufm
6353
새 문서: == 게임의 목표 == 과일을 팔아 판매증서를 모으고, 세트를 완성하세요. == 차례 개요 == === 씨앗 심기 === 농장을 하나 고르고, 거기 있는...
wikitext
text/x-wiki
== 게임의 목표 ==
과일을 팔아 판매증서를 모으고, 세트를 완성하세요.
== 차례 개요 ==
=== 씨앗 심기 ===
농장을 하나 고르고, 거기 있는 모든 씨앗 토큰을 집습니다. 시계방향으로 한 칸씩 이동하며 씨앗 토큰을 하나씩 내려 놓습니다.
''참고: 매우 드물지만 자신의 차례가 시작되었을 때 보관소나 저장창고에만 씨앗 토큰이 있고 어떤 농장에도 씨앗 토큰이 없는 경우가 있을 수 있습니다.''
''이때는 씨앗 심기나 일할 곳 행동을 하지 않고, 보관소(나 부족하면 저장창고)에 있는 씨앗 토큰 3개를 꺼내 저장창고 우측에 있는 농장 3곳에 1개씩 놓은 다음 차례를 마칩니다.''
=== 일할 곳 ===
마지막으로 씨앗 토큰을 내려 놓은 곳이 이번에 일할 곳이 됩니다. 이제 물 뿌리기나 과일 판매 중에서 하나를 고르세요.
마지막 씨앗 토큰이 저장창고 위에 놓이면 즉시 씨앗 심기를 한 번 더 진행합니다. 행동이 가능할 때 행동을 넘길 수는 없습니다.
=== 물 뿌리기나 과일 판매 ===
==== 물 뿌리기 ====
일할 곳에 그려진 과일 혹은 빗방울의 개수만큼, 보관소에서 씨앗 토큰을 가져와 일할 곳에 올립니다.
==== 과일 판매 ====
일할 곳에 그려진 과일과 같은 그림의 과일과 같은 그림의 과일을 시장섬에서 가져옵니다.
알맞은 개수의 씨앗 토큰을 저장창고에서 집어 보관소로 되돌리고, 일할 곳에 있던 모든 씨앗 토큰도 보관소로 되돌립니다.
=== 다음 플레이어 차례로 ===
다음 사람에게 차레가 넘어갑니다.
=== 게임 종료 ===
누군가 시장섬에 표시된 4개의 세트 중 하나를 달성하면, 이번 라운드까지 마치고 게임이 끝납니다.
==== 세트의 종류 ====
* 하우스: 2종류의 판매증서를 각각 2장, 3장 모음
* 독점판매: 1종류의 판매증서를 4장 모음
* 과일 꾸러미: 3종류의 판매증서를 2장씩 모음
* 백화점: 5종류의 판매증서를 1장씩 모음
== 변형 규칙 ==
=== 어린이 농부 ===
시장섬을 사용하지 않고, 판매증서를 섞고 맨 위 3장을 앞면이 보이게 바닥에 놓아 시장을 꾸립니다. 자릿세는 없습니다.
누구든 판매증서를 먼저 5장 모은 사람이 있다면, 그 사람이 즉시 이깁니다.
=== 무작위 설정 ===
게임을 준비할 때 모든 플레이어가 각자 농장카드를 섞어 저장창고의 다음 칸부터 시계 방향으로 카드를 놓습니다.
=== 1인 플레이 ===
==== 준비 ====
판매증서 중 과일별로 1장씩을 꺼내 5장으로 구성된 더미를 만듭니다. 이 더미를 섞고, 맨 위 판매증서를 앞면이 보이게 바닥에 놓습니다.
==== 게임 진행 ====
판매증서는 항상 1장만 앞면으로 놓입니다.
과일 판매를 할 때, 내야 할 씨앗 토큰과 저장창고에 남은 씨앗 토큰을 보관소에 되돌리지 않고 모두 제거하여 이번 게임에서 다시는 사용하지 않습니다.
일할 곳의 씨앗 토큰은 보관소로 되돌립니다.
그 후 새로운 판매증서를 앞면으로 바닥에 놓고 게임을 계속합니다.
==== 게임 종료 ====
아래의 3가지 조건 중 하나라도 만족했다면 즉시 게임이 종료됩니다.
* 보관소에 씨앗이 남아있지 않는 경우 (패배)
* 저장창고에만 씨앗이 있고 농장에는 씨앗이 없는 경우 (패배)
* 판매증서 5장을 모두 모은 경우 (승리)
판매증서 5장을 모두 모았다면 게임에서 승리합니다!
1be1a784bb3ea2aac116eaa2f0d89e28be834384
Gamehelpyaniv
0
216
1364
2022-01-10T02:41:12Z
Ufm
6353
새 문서: == 게임 진행 == 차례가 시작되면 카드를 내거나 야니브를 선언할 수 있습니다. === 카드 내기 / 카드 뽑거나 가져가기 === 아래에 해당되는...
wikitext
text/x-wiki
== 게임 진행 ==
차례가 시작되면 카드를 내거나 야니브를 선언할 수 있습니다.
=== 카드 내기 / 카드 뽑거나 가져가기 ===
아래에 해당되는 카드 묶음을 하나 낼 수 있습니다:
* 카드 1장
* 같은 숫자의 카드 2장 이상 (조커 사용 불가)
* 같은 무늬의 연속된 카드 3장 이상 (조커 사용 가능)
카드를 낸 다음에는 카드 1장을 뽑거나 이전 사람이 낸 카드 1장을 가져옵니다. 카드를 가져오는 경우에는 맨 처음이나 맨 끝 카드만 가져올 수 있습니다.
=== 야니브 선언 ===
손의 카드 점수가 일정 이하라면 카드를 내는 대신 야니브를 선언하고 라운드를 끝낼 수 있습니다.
모두 손의 카드를 공개하여, 선언자의 손의 카드 점수 합계가 가장 낮으면 선언자는 0점을 받지만 그렇지 않다면 손의 카드 + 30점을 받습니다.
선언자 이외의 플레이어는 손의 카드 점수만큼 점수를 받습니다.
손의 카드 점수 합계가 가장 낮은 사람이 라운드에서 승리하여 새 라운드를 시작합니다.
정확히 일정 점수에 도달하면 점수가 줄어듭니다.
=== 게임 종료 ===
라운드마다 받은 점수를 합산하여 한계를 넘으면 게임에서 탈락합니다. 1명만 남을 때까지 게임을 계속 진행합니다.
== 변형규칙 ==
야니브 선언 한도, 탈락 기준, 점수 감소 시점과 감소량, 사용하는 덱의 수, 나눠주는 카드의 수를 고를 수 있습니다.
'바로 내기'와 '보석 덱'도 사용할 수 있습니다.
=== 바로 내기 ===
카드 1장을 낸 뒤 덱에서 뽑은 카드가 같은 숫자의 카드라면 즉시 그 카드를 낼 수 있습니다. 이 결과 손에 카드가 남지 않는다면 다음 턴에 자동으로 야니브를 선언합니다.
=== 보석 덱 ===
카드마다 배경색과 보석 표시가 생깁니다 (K는 2종류가 생깁니다).
낼 수 있는 묶음의 종류가 추가됩니다:
* 같은 배경색의 카드 3장 이상 (조커 사용 가능)
* Q 1장 + 라운드마다 주사위를 굴려 숫자를 지정하는 다이아몬드 카드 1장 (조커로 1장 대체 가능)
7d573166d8440577a22bf006f9fb8fff07a47bfa
1365
1364
2022-01-10T02:41:38Z
Ufm
6353
/* 보석 덱 */
wikitext
text/x-wiki
== 게임 진행 ==
차례가 시작되면 카드를 내거나 야니브를 선언할 수 있습니다.
=== 카드 내기 / 카드 뽑거나 가져가기 ===
아래에 해당되는 카드 묶음을 하나 낼 수 있습니다:
* 카드 1장
* 같은 숫자의 카드 2장 이상 (조커 사용 불가)
* 같은 무늬의 연속된 카드 3장 이상 (조커 사용 가능)
카드를 낸 다음에는 카드 1장을 뽑거나 이전 사람이 낸 카드 1장을 가져옵니다. 카드를 가져오는 경우에는 맨 처음이나 맨 끝 카드만 가져올 수 있습니다.
=== 야니브 선언 ===
손의 카드 점수가 일정 이하라면 카드를 내는 대신 야니브를 선언하고 라운드를 끝낼 수 있습니다.
모두 손의 카드를 공개하여, 선언자의 손의 카드 점수 합계가 가장 낮으면 선언자는 0점을 받지만 그렇지 않다면 손의 카드 + 30점을 받습니다.
선언자 이외의 플레이어는 손의 카드 점수만큼 점수를 받습니다.
손의 카드 점수 합계가 가장 낮은 사람이 라운드에서 승리하여 새 라운드를 시작합니다.
정확히 일정 점수에 도달하면 점수가 줄어듭니다.
=== 게임 종료 ===
라운드마다 받은 점수를 합산하여 한계를 넘으면 게임에서 탈락합니다. 1명만 남을 때까지 게임을 계속 진행합니다.
== 변형규칙 ==
야니브 선언 한도, 탈락 기준, 점수 감소 시점과 감소량, 사용하는 덱의 수, 나눠주는 카드의 수를 고를 수 있습니다.
'바로 내기'와 '보석 덱'도 사용할 수 있습니다.
=== 바로 내기 ===
카드 1장을 낸 뒤 덱에서 뽑은 카드가 같은 숫자의 카드라면 즉시 그 카드를 낼 수 있습니다. 이 결과 손에 카드가 남지 않는다면 다음 턴에 자동으로 야니브를 선언합니다.
=== 보석 덱 ===
카드마다 배경색과 보석 표시가 생깁니다 (K에는 2종류의 배경색이 생깁니다).
낼 수 있는 묶음의 종류가 추가됩니다:
* 같은 배경색의 카드 3장 이상 (조커 사용 가능)
* Q 1장 + 라운드마다 주사위를 굴려 숫자를 지정하는 다이아몬드 카드 1장 (조커로 1장 대체 가능)
c7117728c0f35f3fd9ee6f0bfc93bf68215267b2
1377
1365
2022-01-28T03:16:13Z
Ufm
6353
/* 변형규칙 */
wikitext
text/x-wiki
== 게임 진행 ==
차례가 시작되면 카드를 내거나 야니브를 선언할 수 있습니다.
=== 카드 내기 / 카드 뽑거나 가져가기 ===
아래에 해당되는 카드 묶음을 하나 낼 수 있습니다:
* 카드 1장
* 같은 숫자의 카드 2장 이상 (조커 사용 불가)
* 같은 무늬의 연속된 카드 3장 이상 (조커 사용 가능)
카드를 낸 다음에는 카드 1장을 뽑거나 이전 사람이 낸 카드 1장을 가져옵니다. 카드를 가져오는 경우에는 맨 처음이나 맨 끝 카드만 가져올 수 있습니다.
=== 야니브 선언 ===
손의 카드 점수가 일정 이하라면 카드를 내는 대신 야니브를 선언하고 라운드를 끝낼 수 있습니다.
모두 손의 카드를 공개하여, 선언자의 손의 카드 점수 합계가 가장 낮으면 선언자는 0점을 받지만 그렇지 않다면 손의 카드 + 30점을 받습니다.
선언자 이외의 플레이어는 손의 카드 점수만큼 점수를 받습니다.
손의 카드 점수 합계가 가장 낮은 사람이 라운드에서 승리하여 새 라운드를 시작합니다.
정확히 일정 점수에 도달하면 점수가 줄어듭니다.
=== 게임 종료 ===
라운드마다 받은 점수를 합산하여 한계를 넘으면 게임에서 탈락합니다. 1명만 남을 때까지 게임을 계속 진행합니다.
== 변형규칙 ==
야니브 선언 한도, 탈락 기준, 점수 감소 시점과 감소량, 사용하는 덱의 수, 나눠주는 카드의 수를 고를 수 있습니다.
'바로 내기'도 사용할 수 있습니다.
=== 바로 내기 ===
카드 1장을 낸 뒤 덱에서 뽑은 카드가 같은 숫자의 카드라면 즉시 그 카드를 낼 수 있습니다. 이 결과 손에 카드가 남지 않는다면 다음 턴에 자동으로 야니브를 선언합니다.
a88d63cc97710c5c3ece6bf025beabb56c3254a7
Gamehelpinnovation
0
217
1366
2022-01-13T10:24:03Z
PoroYum
7828
새 문서: ==게임의 시작== 1세대 카드 두 장을 가지고 시작합니다. 하나를 골라 즉시 보드에 내려놓고 다른 하나는 손에 쥐고 있습니다. 내려놓은 카...
wikitext
text/x-wiki
==게임의 시작==
1세대 카드 두 장을 가지고 시작합니다. 하나를 골라 즉시 보드에 내려놓고 다른 하나는 손에 쥐고 있습니다.
내려놓은 카드 이름이 '''영어 이름으로''' 알파벳 순으로 빠른 플레이어부터 시작합니다.
선 플레이어는 첫 턴에서 한 번만의 행동을 얻게 되며, 4인 게임일 경우에는 두번째 플레이어까지 첫 턴에 한 번만 행동할 수 있습니다.
이후, 모든 사람들은 자신의 턴에 두 번의 행동 기회를 얻습니다.
==행동==
첫 턴의 선 플레이어(들)을 제외하고(위의 게임의 시작 참고), 플레이어들은 매 턴마다 아래 4가지 행동 중 2개의 행동을 선택해 행동해야 합니다. (동일한 행동을 두 번 할 수 있음)
;카드 뽑기
:카드 더미에서, 자신의 보드(공간)에서 가장 높은 시대 숫자를 가진 카드와 동일한 시대의 카드를 뽑습니다. 해당 시대 카드 더미가 비어 있다면, 다음으로 높은 숫자 카드를 뽑습니다. 카드 뽑기에 대한 이 규칙은 "'''카드를 뽑는'''" 키워드를 가진 모든 효과에도 적용됩니다.
;내려놓기
:손에 있는 카드를 자신의 보드에 내려놓습니다. 이미 내려놓아진 카드 중 같은 색상의 카드 위에 내려놓으며, 보드에 같은 색상의 카드가 없다면 빈 공간에 내려놓습니다. 만약 해당 색상의 카드 스택이 펼쳐져 있다면, 새 카드를 내려놓아도 펼쳐짐은 유지됩니다.
;도그마
:보드에 내려놓아진 카드 중 맨 위의 카드를 선택해 카드의 능력을 발동합니다. 해당 능력이 필요로 하는 기술 아이콘과 같은 종류의 아이콘을 자신보다 적게 가진 모든 상대는 "요구"효과를 따라야 합니다. (보드에 놓인 카드에 그려진 기술 아이콘의 개수, 우측 플레이어 정보란에서도 확인할 수 있음)
:자신과 같거나 많은 수의 같은 종류 기술 아이콘을 가진 상대는 "요구" 효과가 아닌 비요구 능력을 공유합니다. 효과는 시계방향으로 실행되어 본인을 마지막으로 끝납니다. 만약 공유한 비요구 효과가 게임에 영향을 미쳤다면, 도그마 행동이 끝날 때 한 장의 카드를 무료로 카드 더미에서 뽑을 수 있습니다.
;달성
:해당 시대의 5배 이상의 점수가 점수 더미에 있고, 자신의 보드의 카드 스택 맨 위에 시대 업적 숫자 이상의 카드가 놓여 있으면 해당 시대 업적을 달성할 수 있습니다. 예를 들어 1시대 업적카드를 원한다면 점수 5점, 보드에 아무 카드가 필요합니다. 2시대 업적카드를 달성하려면 점수 10점과 보드에 2시대 이상 카드 최소 한장... 이후 동일하게 필요합니다.
:포인트는 소모되지 않고 유지됩니다. 5종의 특수업적 카드는 달성 시 행동을 소모할 필요가 없으며, 조건이 충족되는 대로 달성할 수 있습니다.
==게임의 끝==
게임은 다음 세 가지 엔딩이 있습니다 :
;업적 달성
:플레이어가 아래 업적 개수를 달성하면 즉시 게임이 끝납니다. (도그마 이펙트 중에도)
: - 2인 : 6개 업적
: - 3인 : 5개 업적
: - 4인 : 4개 업적
: - 4인(팀게임 변형) : 팀 동료 총합 6개 성과
점수는 관계 없이 먼저 6개의 업적을 달성한 사람이 승자입니다.
;점수
:누군가가 11시대 이상의 카드를 뽑으려고 할 때 일어납니다. 도그마 이펙트 중에도 즉시 종료되며, 승자는 점수 더미의 점수가 가장 많은 사람이 됩니다. 팀전에서는 팀원들의 점수를 합산합니다. (동점일 경우, 업적을 합산합니다)
;도그마
:몇 장의 카드의 도그마 효과는 어떤 조건이 충족되었을 때 승리합니다. 만약 조건에 부합하는 사람이 한 명 이상이라면, 경기는 종료되지 않고 계속됩니다. (팀게임인 경우 동료 제외 : 동료와 자신이 승리 조건에 부합하면 승리)
==팁==
할 수 있는 만큼 최대한 하고 나머지는 무시하세요.
이 방법은 애매한 상황을 최대한 활용할 수 있도록 해 줄 것입니다.
다음과 같은 활용법이 있습니다:
* 교환이 균등할 필요는 없다. 상황에 따라 2장의 카드를 한두 장의 카드 혹은 4장으로, 심지어
10장의 카드를 0장과 교환할 수도 있다.
* 카드가 부족하여 효과 요구 사항을 충족할 수 없는 경우 모든 카드를 처리할 수 있다.
* 하지만, '''"할 수 있다"'''키워드의 효과를 내기 위해서 3장의 카드를 반납해야 하는데, 3장 미만의 카드를 가지고 있다면 건너뛰어야 한다.
<br/>
메모에 커서를 올리면 작업 및 키워드에 대한 주의사항이 나타납니다.
==게임 에디션 및 차이점==
이 게임은 2010년 Asmadi Games가 처음으로 출시했습니다. <br/>
2011년, Iello가 같은 방식과 카드 효과를 가지고 있지만 다른 용어를 사용하는 게임의 다른 판을 출시했습니다.<br/>
최근에 Asmadi Games는 오리지널 게임과 모든 확장팩을 그래픽 리뉴얼과 함게 "이노베익션 디럭스"로 모았으며 밸런스를 위해 9개의 카드를 약간 수정했습니다.
온라인판은 Asmadi Games의 초판을 바탕으로 만들어졌습니다. 규칙의 경우 다음 중 하나를 선택할 수 있습니다.
* 최종판(기본값) : "이노베이션 디럭스" 팩의 규칙입니다.
* 초판 : Asmadi 오리지널의 규칙입니다. Iello판과도 일치합니다.
----
이 문서는 이 사이트에서 제공한 기본 영어 게임 도움말을 직접 번역하여 작성하였습니다.
헷갈릴 수 있는 부분은 직접 작성하여 추가했습니다.
9a97204122f9a2a03b0f0bb718fe1f069004dccb
Gamehelploveletter
0
177
1367
1231
2022-01-15T15:50:51Z
Nilzzzzy
7482
왜 카페 홍보함? 이러라고 있는 곳이 아닌데
wikitext
text/x-wiki
승리 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우 승리<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
- 토큰을 다 모았을 경우 승리<br>
(2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명이 플레이 할 경우, 4개)<br>
<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다<br>
2. 2장의 카드를 비교 후, 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다<br>
<br>
카드 기능<br>
1. 경비병: 상대방이 가진 카드를 추측(병사를 제외한 추측)하고 추측이 맞았을 경우에는 상대방은 탈락한다<br>
2. 성직자: 다른 1명의 카드를 볼 수 있다<br>
3. 남작: 다른 1명을 지목하여 대결한다. 손에 든 카드의 숫자가 더 낮은 사람은 라운드에서 탈락한다<br>
4. 시녀: 다음 차례가 올 때까지 어떠한 카드의 효과도 받지 않는다<br>
5. 왕자: 자신이나 다른 1명을 지목해 손에 든 모든 카드를 버리게 하고 다시 덱에서 한 장 가져온다<br>
6. 왕: 다른 1명과 자신의 카드를 모두 바꾼다<br>
7. 백작부인: 5번 또는 6번(왕자, 왕) 카드와 같이 들고 있다면 반드시 이 카드를 버린다<br>
8. 공주: 이 카드를 버리게 되면 라운드에서 탈락한다<br>
6f06ab9d96eb77b7bb54a741830a306423e4c18c
1368
1367
2022-01-15T16:33:53Z
Nilzzzzy
7482
wikitext
text/x-wiki
승리 조건
- 토큰을 다 모았을 경우 승리<br>
2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명 이상이 플레이 할 경우, 4개
토큰을 모으는 조건
- 모든 인원이 탈락하고 1명만 남았을 경우
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리
게임 방법
1. 자신의 차례가 되면 덱에서 1장을 가져온다
2. 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다
카드 기능
1. 경비병(5장): 상대방이 가진 카드를 추측(병사를 제외한 추측)하고 추측이 맞았을 경우에는 상대방은 탈락한다
2. 성직자(2장): 다른 1명의 카드를 볼 수 있다
3. 남작(2장): 다른 1명을 지목하여 대결한다. 손에 든 카드의 숫자가 더 낮은 사람은 라운드에서 탈락한다
4. 시녀(2장): 다음 차례가 올 때까지 어떠한 카드의 효과도 받지 않는다
5. 왕자(2장): 자신이나 다른 1명을 지목해 손에 든 모든 카드를 버리게 하고 다시 덱에서 한 장 가져온다
6. 왕(1장): 다른 1명과 자신의 카드를 모두 바꾼다
7. 백작부인(1장): 5번 또는 6번(왕자, 왕) 카드와 같이 들고 있다면 반드시 이 카드를 버린다
8. 공주(1장): 이 카드를 버리게 되면 라운드에서 탈락한다
5인 이상 추가 카드 기능
0.
0.
b8c5b9f6f5162916a4462a3052bd74760ed3a8b9
1369
1368
2022-01-15T16:37:52Z
Nilzzzzy
7482
wikitext
text/x-wiki
승리 조건<br>
- 토큰을 다 모았을 경우 승리<br>
2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명 이상이 플레이 할 경우, 4개<br>
토큰을 모으는 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다.<br>
2. 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다.<br>
카드 기능<br>
1. 경비병(5장): 상대방이 가진 카드를 추측(병사를 제외한 추측)하고 추측이 맞았을 경우에는 상대방은 탈락한다.<br>
2. 성직자(2장): 다른 1명의 카드를 볼 수 있다.<br>
3. 남작(2장): 다른 1명을 지목하여 대결한다. 손에 든 카드의 숫자가 더 낮은 사람은 라운드에서 탈락한다.<br>
4. 시녀(2장): 다음 차례가 올 때까지 어떠한 카드의 효과도 받지 않는다.<br>
5. 왕자(2장): 자신이나 다른 1명을 지목해 손에 든 모든 카드를 버리게 하고 다시 덱에서 한 장 가져온다.<br>
6. 왕(1장): 다른 1명과 자신의 카드를 모두 바꾼다.<br>
7. 백작부인(1장): 5번 또는 6번(왕자, 왕) 카드와 같이 들고 있다면 반드시 이 카드를 버린다.<br>
8. 공주(1장): 이 카드를 버리게 되면 라운드에서 탈락한다.<br>
5인 이상 추가 카드 기능<br>
0.
0.
0afe584b7b6fb9d6c3cf6ce4126a9a58d15dbb6a
1370
1369
2022-01-15T16:38:17Z
Nilzzzzy
7482
wikitext
text/x-wiki
승리 조건<br>
- 토큰을 다 모았을 경우 승리<br>
2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명 이상이 플레이 할 경우, 4개<br>
토큰을 모으는 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다.<br>
2. 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다.<br>
카드 기능<br>
1. 경비병(5장): 상대방이 가진 카드를 추측(병사를 제외한 추측)하고 추측이 맞았을 경우에는 상대방은 탈락한다.<br>
2. 성직자(2장): 다른 1명의 카드를 볼 수 있다.<br>
3. 남작(2장): 다른 1명을 지목하여 대결한다. 손에 든 카드의 숫자가 더 낮은 사람은 라운드에서 탈락한다.<br>
4. 시녀(2장): 다음 차례가 올 때까지 어떠한 카드의 효과도 받지 않는다.<br>
5. 왕자(2장): 자신이나 다른 1명을 지목해 손에 든 모든 카드를 버리게 하고 다시 덱에서 한 장 가져온다.<br>
6. 왕(1장): 다른 1명과 자신의 카드를 모두 바꾼다.<br>
7. 백작부인(1장): 5번 또는 6번(왕자, 왕) 카드와 같이 들고 있다면 반드시 이 카드를 버린다.<br>
8. 공주(1장): 이 카드를 버리게 되면 라운드에서 탈락한다.<br>
5인 이상 추가 카드 기능<br>
0.
0.
16576a7f98ba11f015620ad86c40be6f54ba7c74
1371
1370
2022-01-15T16:40:34Z
Nilzzzzy
7482
wikitext
text/x-wiki
승리 조건<br>
- 토큰을 다 모았을 경우 승리<br>
2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명 이상이 플레이 할 경우, 4개<br>
토큰을 모으는 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다.<br>
2. 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다.<br>
카드 기능<br>
1. 경비병(5장): 상대방이 가진 카드를 추측(병사를 제외한 추측)하고 추측이 맞았을 경우에는 상대방은 탈락한다.<br>
2. 성직자(2장): 다른 1명의 카드를 볼 수 있다.<br>
3. 남작(2장): 다른 1명을 지목하여 대결한다. 손에 든 카드의 숫자가 더 낮은 사람은 라운드에서 탈락한다.<br>
4. 시녀(2장): 다음 차례가 올 때까지 어떠한 카드의 효과도 받지 않는다.<br>
5. 왕자(2장): 자신이나 다른 1명을 지목해 손에 든 모든 카드를 버리게 하고 다시 덱에서 한 장 가져온다.<br>
6. 왕(1장): 다른 1명과 자신의 카드를 모두 바꾼다.<br>
7. 백작부인(1장): 5번 또는 6번(왕자, 왕) 카드와 같이 들고 있다면 반드시 이 카드를 버린다.<br>
8. 공주(1장): 이 카드를 버리게 되면 라운드에서 탈락한다.<br>
5인 이상 추가 카드 기능<br>
0. 광대(1장): <br>
0. 암살자(1장): <br>
1. 경비병(추가 3장): <br>
2. : <br>
3. 남작부인 : <br>
4. <br>
5. <br>
6. <br>
7. <br>
9. <br>
1c50ea88212d5a18b2a2e929104039dee69fd391
1372
1371
2022-01-16T20:47:09Z
Nilzzzzy
7482
wikitext
text/x-wiki
승리 조건<br>
- 토큰을 다 모았을 경우 승리<br>
2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명 이상이 플레이 할 경우, 4개<br>
토큰을 모으는 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다.<br>
2. 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다.<br>
카드 기능<br>
1. 경비병(5장): 상대방이 가진 카드를 추측(병사를 제외한 추측)하고 추측이 맞았을 경우에는 상대방은 탈락한다.<br>
2. 성직자(2장): 다른 1명의 카드를 볼 수 있다.<br>
3. 남작(2장): 다른 1명을 지목하여 대결한다. 손에 든 카드의 숫자가 더 낮은 사람은 라운드에서 탈락한다.<br>
4. 시녀(2장): 다음 차례가 올 때까지 어떠한 카드의 효과도 받지 않는다.<br>
5. 왕자(2장): 자신이나 다른 1명을 지목해 손에 든 모든 카드를 버리게 하고 다시 덱에서 한 장 가져온다.<br>
6. 왕(1장): 다른 1명과 자신의 카드를 모두 바꾼다.<br>
7. 백작부인(1장): 5번 또는 6번(왕자, 왕) 카드와 같이 들고 있다면 반드시 이 카드를 버린다.<br>
8. 공주(1장): 이 카드를 버리게 되면 라운드에서 탈락한다.<br>
5인 이상 추가 카드 기능<br>
0. 광대(1장): <br>
0. 암살자(1장): 이 카드를 쥐고있을 때 누군가 경비병으로 당신을 지목하면, 그 사람이 대신 라운드에서 탈락한 뒤 자신은 이카드를 버리고 새 카드를 뽑습니다.<br>
1. 경비병(추가 3장): <br>
2. 추기경(2장): 플레이어 2명을 골라 패를 교환시킨 뒤 둘 중 한 명의 패를 봅니다. <br>
3. 남작부인(2장) : 다른 플레이어 1~2명을 골라 패를 봅니다.<br>
4. 아첨꾼(4장): 원하는 플레이어 한 명을 고릅니다. 만약 다음에 사용되는 카드의 효과에서 플레이어를 선택해야 한다면, 이 카드로 고른 플레이어를 반드시 포합시켜야 합니다.<br>
5. 백작(2장): <br>
6. 치안관(1장): <br>
7. 왕태후(1장): <br>
9. 주교(1장): 다른 플레이어 한 명을 골라 그 플레이어의 패를 추측합니다. (1번 카드를 지명할 수는 없습니다.) 만약 패를 맞췄다면 1점을 얻습니다. 상대방은 그 카드를 버리고 새 카드를 뽑을 수도 있습니다. 라운드가 끝날 때는 공주가 주교를 이깁니다.<br>
be466fc00d2551d55a5060f55bb66703f9ed5dbc
1373
1372
2022-01-16T20:50:22Z
Nilzzzzy
7482
wikitext
text/x-wiki
승리 조건<br>
- 토큰을 다 모았을 경우 승리<br>
2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명 이상이 플레이 할 경우, 4개<br>
토큰을 모으는 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다.<br>
2. 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다.<br>
카드 기능<br>
1. 경비병(5장): 상대방이 가진 카드를 추측(병사를 제외한 추측)하고 추측이 맞았을 경우에는 상대방은 탈락한다.<br>
2. 성직자(2장): 다른 1명의 카드를 볼 수 있다.<br>
3. 남작(2장): 다른 1명을 지목하여 대결한다. 손에 든 카드의 숫자가 더 낮은 사람은 라운드에서 탈락한다.<br>
4. 시녀(2장): 다음 차례가 올 때까지 어떠한 카드의 효과도 받지 않는다.<br>
5. 왕자(2장): 자신이나 다른 1명을 지목해 손에 든 모든 카드를 버리게 하고 다시 덱에서 한 장 가져온다.<br>
6. 왕(1장): 다른 1명과 자신의 카드를 모두 바꾼다.<br>
7. 백작부인(1장): 5번 또는 6번(왕자, 왕) 카드와 같이 들고 있다면 반드시 이 카드를 버린다.<br>
8. 공주(1장): 이 카드를 버리게 되면 라운드에서 탈락한다.<br>
5인 이상 추가 카드 기능<br>
0. 광대(1장): 다른 플레이어 한 명을 골라 광대 토큰을 줍니다. 만약 그 플레이어가 이번 라운드에서 승리하면 1점을 얻습니다.<br>
0. 암살자(1장): 이 카드를 쥐고있을 때 누군가 경비병으로 당신을 지목하면, 그 사람이 대신 라운드에서 탈락한 뒤 자신은 이카드를 버리고 새 카드를 뽑습니다.<br>
1. 경비병(추가 3장): 효과 동일, 일러스트가 다르다.<br>
2. 추기경(2장): 플레이어 2명을 골라 패를 교환시킨 뒤 둘 중 한 명의 패를 봅니다. <br>
3. 남작부인(2장) : 다른 플레이어 1~2명을 골라 패를 봅니다.<br>
4. 아첨꾼(4장): 원하는 플레이어 한 명을 고릅니다. 만약 다음에 사용되는 카드의 효과에서 플레이어를 선택해야 한다면, 이 카드로 고른 플레이어를 반드시 포합시켜야 합니다.<br>
5. 백작(2장): 라운드가 끝날 때, 쓴 카드더미에 이 카드가 있다면 내 카드의 가치가 +1 올라갑니다. 동률은 일반적으로 해결합니다.<br>
6. 치안관(1장): <br>
7. 왕태후(1장): <br>
9. 주교(1장): 다른 플레이어 한 명을 골라 그 플레이어의 패를 추측합니다. (1번 카드를 지명할 수는 없습니다.) 만약 패를 맞췄다면 1점을 얻습니다. 상대방은 그 카드를 버리고 새 카드를 뽑을 수도 있습니다. 라운드가 끝날 때는 공주가 주교를 이깁니다.<br>
643c34df0ed433f33ab3f8ae4f90e5912dab0896
1374
1373
2022-01-16T20:55:43Z
Nilzzzzy
7482
wikitext
text/x-wiki
승리 조건<br>
- 토큰을 다 모았을 경우 승리<br>
2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명 이상이 플레이 할 경우, 4개<br>
토큰을 모으는 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다.<br>
2. 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다.<br>
카드 기능<br>
1. 경비병(5장): 다른 플레이어 한 명을 골라 그 플레이어의 패를 추측합니다.(1번 카드를 지명할 수는 없습니다)만약 패를 맞췄다면 그 플레이어는 이번 라운드에서 탈락합니다.<br>
2. 성직자(2장): 다른 플레이어의 패를 봅니다.<br>
3. 남작(2장): 다른 플레이어 한 명을 골라 서로의 패를 비밀리에 비교합니다. 더 낮은 카드를 가진 플레이어는 이번 라운드에서 탈락합니다.<br>
4. 시녀(2장): 다음 턴까지 다른 플레이어들의 카드에 영향을 받지 않습니다.<br>
5. 왕자(2장): 한 명을 지목하여 패를 버리고 새 카드를 뽑게 합니다.(자신도 선택 가능)<br>
6. 왕(1장): 다른 플레이어와 패를 교환합니다.<br>
7. 백작부인(1장): 왕(6) 혹은 왕자(5) 카드와 이 카드를 함께 들고 있다면, 반드시 이카드를 버려야 합니다.<br>
8. 공주(1장):만약 당신이 이카드를 버리게 된다면, 당신은 이번 라운드에서 탈락합니다.<br>
5인 이상 추가 카드 기능<br>
0. 광대(1장): 다른 플레이어 한 명을 골라 광대 토큰을 줍니다. 만약 그 플레이어가 이번 라운드에서 승리하면 1점을 얻습니다.<br>
0. 암살자(1장): 이 카드를 쥐고있을 때 누군가 경비병으로 당신을 지목하면, 그 사람이 대신 라운드에서 탈락한 뒤 자신은 이카드를 버리고 새 카드를 뽑습니다.<br>
1. 경비병(추가 3장): 효과 동일, 일러스트가 다르다.<br>
2. 추기경(2장): 플레이어 2명을 골라 패를 교환시킨 뒤 둘 중 한 명의 패를 봅니다. <br>
3. 남작부인(2장) : 다른 플레이어 1~2명을 골라 패를 봅니다.<br>
4. 아첨꾼(4장): 원하는 플레이어 한 명을 고릅니다. 만약 다음에 사용되는 카드의 효과에서 플레이어를 선택해야 한다면, 이 카드로 고른 플레이어를 반드시 포합시켜야 합니다.<br>
5. 백작(2장): 라운드가 끝날 때, 쓴 카드더미에 이 카드가 있다면 내 카드의 가치가 +1 올라갑니다. 동률은 일반적으로 해결합니다.<br>
6. 치안관(1장): 당신이 탈락했을 때, 쓴 카드더미에 이 카드가 있다면 1점을 얻습니다.<br>
7. 왕태후(1장): 다른 플레이어 한 명을 골라 서로의 패를 비밀리에 비교합니다. 더 높은 카드를 가진 플레이어는 이번 라운드에서 탈락합니다.<br>
9. 주교(1장): 다른 플레이어 한 명을 골라 그 플레이어의 패를 추측합니다. (1번 카드를 지명할 수는 없습니다.) 만약 패를 맞췄다면 1점을 얻습니다. 상대방은 그 카드를 버리고 새 카드를 뽑을 수도 있습니다. 라운드가 끝날 때는 공주가 주교를 이깁니다.<br>
bdcf966cc472fbf471d1762450ad69ac05d2438c
Tips president
0
218
1375
2022-01-24T02:08:44Z
SEEXXKING
7845
새 문서: 낮은 카드를 먼저 사용하려고 노력하세요; 가장 높은 카드를 너무 빨리 사용하지 마세요.
wikitext
text/x-wiki
낮은 카드를 먼저 사용하려고 노력하세요; 가장 높은 카드를 너무 빨리 사용하지 마세요.
c957c0f8b54f31ce74254abe4ce3491bcc1b0735
Gamehelptwinpalms
0
219
1376
2022-01-25T11:34:55Z
Ufm
6353
새 문서: == 개요 == 트윈 팜즈는 아름다운 해변가 느낌이 드는, 전통에서 벗어난 트릭테이킹 카드 게임입니다. 트윈 팜즈는 여러 라운드에 걸쳐 진...
wikitext
text/x-wiki
== 개요 ==
트윈 팜즈는 아름다운 해변가 느낌이 드는, 전통에서 벗어난 트릭테이킹 카드 게임입니다.
트윈 팜즈는 여러 라운드에 걸쳐 진행됩니다. 라운드 수는 참가 인원에 따라 다릅니다 (2/3/4/5명 = 6/6/8/5라운드).
== 게임 진행 ==
라운드는 아래의 순서에 따라 진행됩니다:
# 카드 나눠주기
# 공약과 베팅
# 카드 내기
# 점수 획득
=== 카드 나눠주기 ===
카드를 섞고 각각 10장씩 나눠줍니다.
쉬움 모드에서는 야자수 무늬만, 보통 모드에서는 야자수와 돌고래 무늬를, 상급/최상급 모드에서는 야자수, 돌고래, 선글라스 무늬를 사용합니다.
한 무늬는 0 ~ 10까지의 카드와 와일드 카드가 2장씩으로 총 24장의 카드로 구성됩니다.
=== 공약과 베팅 ===
공약 카드를 비밀리에 골라 가져갈 트릭 수를 공약합니다.
공약 달성에 점수를 걸 수도 있습니다. 베팅할 점수는 고른 베팅 카드에 따라 결정됩니다. '베팅 없음' 모드에서는 베팅으로 점수를 걸 수 없습니다.
=== 카드 내기 ===
시작 플레이어 토큰을 가진 플레이어가 첫 트릭을 시작합니다.
각자 손에서 카드 2장을 골라 앞면으로 냅니다.
와일드 카드를 내면 와일드 카드를 0 ~ 10 중 무슨 숫자로 쓸지 고릅니다.
카드를 내면 참조표에 나온 대로 순위를 매깁니다. 가장 순위가 높은 사람이 트릭을 가져갑니다.
* 숫자가 같은 1쌍은 숫자가 다른 1쌍을 이깁니다.
* 무늬 중에서는 야자수가 가장 높고, 돌고래, 선글라스, 2무늬 조합 순서로 이어집니다.
순위가 같으면 2장 중 더 큰 숫자가 더 높은 사람, 더 큰 숫자도 같으면 더 작은 숫자가 더 높은 사람이 이깁니다.
순위와 2장의 숫자까지 모두 같으면 무승부로 취급하여 카드를 버립니다. 무승부로는 트릭을 가져갈 수 없습니다.
모두 무승부라면 아무도 트릭을 가져가지 않고 깔린 카드를 모두 버린 뒤, 지난 트릭의 선이 다시 새 트릭의 선이 됩니다.
=== 점수 획득 ===
각자 카드를 모두 내면 공약 카드와 베팅에 따라 점수를 계산합니다.
첫 트릭의 시작 플레이어는 시작 플레이어 토큰을 다음 플레이어에게 넘기고 새 라운드를 시작합니다.
정해진 수만큼의 라운드를 마치면 게임이 끝나고, 점수가 가장 높은 플레이어가 승리합니다!
1등이 여러 명이라면 단독 1등이 나올 때까지 연장전을 진행합니다.
== 플레이어 설정 옵션 ==
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
=== 카드 모양 ===
* '''기본''': 기본 카드 이미지를 사용합니다.
* 단순: 숫자를 보기 더 편한 단순한 카드 이미지를 사용합니다.
=== 글꼴 ===
* '''테마풍''': 해변의 분위기에 어울리는 글꼴을 사용합니다.
* BGA 기본: BGA 기본 글꼴을 사용합니다.
=== 효과음 재생 ===
* '''네''': 카드를 나눠주거나, 카드를 내거나, 점수를 획득할 때 효과음을 재생합니다.
* 아니요: 특수 효과음을 재생하지 않습니다.
67382a851fedcc770904f6dd6e880885061506ee
1395
1376
2022-03-06T00:16:33Z
Ufm
6353
wikitext
text/x-wiki
== 개요 ==
트윈 팜즈는 아름다운 해변가 느낌이 드는, 전통에서 벗어난 트릭테이킹 카드 게임입니다.
트윈 팜즈는 여러 라운드에 걸쳐 진행됩니다. 라운드 수는 참가 인원에 따라 다릅니다 (2/3/4/5명 = 6/6/8/5라운드).
== 게임 진행 ==
라운드는 아래의 순서에 따라 진행됩니다:
# 카드 나눠주기
# 공약과 베팅
# 카드 내기
# 점수 획득
=== 카드 나눠주기 ===
카드를 섞고 각각 10장씩 나눠줍니다.
쉬움 모드에서는 야자수 무늬만, 보통 모드에서는 야자수와 돌고래 무늬를, 상급/최상급 모드에서는 야자수, 돌고래, 선글라스 무늬를 사용합니다.
한 무늬는 0 ~ 10까지의 카드와 와일드 카드가 2장씩으로 총 24장의 카드로 구성됩니다.
=== 공약과 베팅 ===
공약 카드를 비밀리에 골라 가져갈 트릭 수를 공약합니다.
공약 달성에 점수를 걸 수도 있습니다. 베팅할 점수는 고른 베팅 카드에 따라 결정됩니다. '베팅 없음' 모드에서는 베팅으로 점수를 걸 수 없습니다.
=== 카드 내기 ===
시작 플레이어 토큰을 가진 플레이어가 첫 트릭을 시작합니다.
각자 손에서 카드 2장을 골라 앞면으로 냅니다.
와일드 카드를 내면 와일드 카드를 0 ~ 10 중 무슨 숫자로 쓸지 고릅니다.
카드를 내면 참조표에 나온 대로 순위를 매깁니다. 가장 순위가 높은 사람이 트릭을 가져갑니다.
* 숫자가 같은 1쌍은 숫자가 다른 1쌍을 이깁니다.
* 무늬 중에서는 야자수가 가장 높고, 돌고래, 선글라스, 2무늬 조합 순서로 이어집니다.
순위가 같으면 2장 중 더 큰 숫자가 더 높은 사람, 더 큰 숫자도 같으면 더 작은 숫자가 더 높은 사람이 이깁니다.
순위와 2장의 숫자까지 모두 같으면 무승부로 취급하여 카드를 버립니다. 무승부로는 트릭을 가져갈 수 없습니다.
모두 무승부라면 아무도 트릭을 가져가지 않고 깔린 카드를 모두 버린 뒤, 지난 트릭의 선이 다시 새 트릭의 선이 됩니다.
=== 점수 획득 ===
각자 카드를 모두 내면 공약 카드와 베팅에 따라 점수를 계산합니다.
첫 트릭의 시작 플레이어는 시작 플레이어 토큰을 다음 플레이어에게 넘기고 새 라운드를 시작합니다.
정해진 수만큼의 라운드를 마치면 게임이 끝나고, 점수가 가장 높은 플레이어가 승리합니다!
== 플레이어 설정 옵션 ==
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
=== 카드 모양 ===
* '''기본''': 기본 카드 이미지를 사용합니다.
* 단순: 숫자를 보기 더 편한 단순한 카드 이미지를 사용합니다.
=== 글꼴 ===
* '''테마풍''': 해변의 분위기에 어울리는 글꼴을 사용합니다.
* BGA 기본: BGA 기본 글꼴을 사용합니다.
=== 효과음 재생 ===
* '''네''': 카드를 나눠주거나, 카드를 내거나, 점수를 획득할 때 효과음을 재생합니다.
* 아니요: 특수 효과음을 재생하지 않습니다.
4196552fec3097f98e10936d835f36f3558a21a7
Gamehelpschroedingerscats
0
220
1378
2022-02-01T13:51:36Z
Producer Zenn
7863
새 문서: ★세팅 a) 각 플레이어마다 한 장의 박사 카드가 지급되고 폐기 더미 안에 한 장의 박사 카드를 둡니다. b) 각 플레이어에게 플레이어 수와...
wikitext
text/x-wiki
★세팅
a) 각 플레이어마다 한 장의 박사 카드가 지급되고 폐기 더미 안에 한 장의 박사 카드를 둡니다.
b) 각 플레이어에게 플레이어 수와 동일한 상자 수를 나누어 줍니다. (예: 플레이어 4명일 시 상자카드 4장)
c) 연구 덱을 세팅한다.
★박스 카드 종류
살아있는 고양이 카드
가장 낮은 랭크의 카드입니다. 총 20장이 덱에 들어있습니다.
죽은 고양이 카드
살아있는 고양이보다는 랭크가 높지만 빈 상자보다는 순위가 낮습니다.총 20장이 덱에 들어있습니다.
빈 박스
가장 높은 랭크의 카드입니다. 가설을 제시할 때 두 배의 가치를 지닙니다. 총 8장이 덱에 들어있습니다.
하이젠베르크
이것은 와일드 카드(조커)입니다. 이것은 항상 직전에 제시되었던 가설과 동일한 카드로 간주됩니다. 따라서 하이젠베르크를 가지고 가설을 세우는 것은 불가능합니다. 총 4장이 덱에 들어있습니다.
★내 턴에 할 일
a-1) 가설 배팅 패널에서 배팅을 합니다. 배팅이란, 나를 포함한 전원이 손에 들고 있는 패 중에 과연 '살아있는/죽은/빈' 카드가 모두 몇 장인지를 찍는 것입니다.
배팅을 할 때는 항상 직전에 제시된 가설보다 더 높은 랭크-즉, 오른쪽 또는 하단-으로만 상위입찰을 할 수 있습니다.
b) 그런 다음 현재 입찰과 일치하는 유형의 카드를 내려놓아 결과를 보여줄 수 있습니다.(보여주지 않아도 됩니다) ex)살아있는 고양이가 5마리 있다고 배팅했다면, 손에 든 카드 중 살아있는 고양이 카드를 한 장 공개할 수 있다.
그런 다음 원하는 만큼 손에 남은 상자(카드)를 버리고 버린 장수만큼 다시 가져올 수 있습니다.
c) 박사학위(고양이 물리학자 카드)를 공개할 수 있습니다. 이 경우 한번 사용하면 게임이 끝날 때까지 더이상의 박사학위 카드는 사용이 불가능합니다.
a-2) 만약 당신이 직전에 배팅한 사람의 가설이 거짓이라고 생각한다면 의문을 제기합니다. 그러면 모두가 손에 든 카드가 공개되고, 모두가 가진 고양이 카드의 개수가 합산되어 가설이 맞는지 아닌지 세어볼 수 있습니다.
앞사람의 가설이 틀렸다면 그 사람이 게임에서 아웃되고, 가설이 맞았다면 의문을 제기한 사람이 아웃됩니다.
박사 학위 능력
이름-능력 순
Albert Felinestein 당신의 연구를 버리고 버린 만큼 다시 뽑을 수 있습니다.
Cecelia Pounce 이 연구에 살아있는 고양이 숫자 2마리를 더합니다.
Madam Purrie 공개되어 있는 살아있는 고양이 카드를 모두 버립니다.
Maria Goeppertmeower 이 연구에 빈 박스를 하나 더합니다.
Mittens Faraday 공개되어 있는 죽은 고양이 카드를 모두 버린다.
Neil Degrasse Tabby 공개된 물리학자 카드의 효과를 복사합니다.
Sally Prride 이번 턴에 버려진 카드 더미를 확인할 수 있습니다.
Sir Isaac Mewton 연구 덱에서 추가로 2장의 카드를 뽑습니다.
Stephen Pawking 당신의 가설 세우기 단계를 패스합니다.
Whiskers Feyncat 이 연구에 하이젠베르크 카드 개수를 제외합니다.
cffd2a7d53fce32a097a2b5f8293ce3708315148
1379
1378
2022-02-01T13:53:16Z
Producer Zenn
7863
wikitext
text/x-wiki
★세팅
a) 각 플레이어마다 한 장의 박사 카드가 지급되고 폐기 더미 안에 한 장의 박사 카드를 둡니다.
b) 각 플레이어에게 플레이어 수와 동일한 상자 수를 나누어 줍니다. (예: 플레이어 4명일 시 상자카드 4장)
c) 연구 덱을 세팅한다.
★박스 카드 종류
살아있는 고양이 카드
가장 낮은 랭크의 카드입니다. 총 20장이 덱에 들어있습니다.
죽은 고양이 카드
살아있는 고양이보다는 랭크가 높지만 빈 상자보다는 순위가 낮습니다.총 20장이 덱에 들어있습니다.
빈 박스
가장 높은 랭크의 카드입니다. 가설을 제시할 때 두 배의 가치를 지닙니다. 총 8장이 덱에 들어있습니다.
하이젠베르크
이것은 와일드 카드(조커)입니다. 이것은 항상 직전에 제시되었던 가설과 동일한 카드로 간주됩니다. 따라서 하이젠베르크를 가지고 가설을 세우는 것은 불가능합니다. 총 4장이 덱에 들어있습니다.
★내 턴에 할 일
a-1) 가설 배팅 패널에서 배팅을 합니다. 배팅이란, 나를 포함한 전원이 손에 들고 있는 패 중에 과연 '살아있는/죽은/빈' 카드가 모두 몇 장인지를 찍는 것입니다.
배팅을 할 때는 항상 직전에 제시된 가설보다 더 높은 랭크-즉, 오른쪽 또는 하단-으로만 상위입찰을 할 수 있습니다.
b) 그런 다음 현재 입찰과 일치하는 유형의 카드를 내려놓아 결과를 보여줄 수 있습니다.(보여주지 않아도 됩니다) ex)살아있는 고양이가 5마리 있다고 배팅했다면, 손에 든 카드 중 살아있는 고양이 카드를 한 장 공개할 수 있다.
그런 다음 원하는 만큼 손에 남은 상자(카드)를 버리고 버린 장수만큼 다시 가져올 수 있습니다.
c) 박사학위(고양이 물리학자 카드)를 공개할 수 있습니다. 이 경우 한번 사용하면 게임이 끝날 때까지 더이상의 박사학위 카드는 사용이 불가능합니다.
a-2) 만약 당신이 직전에 배팅한 사람의 가설이 거짓이라고 생각한다면 의문을 제기합니다.
그러면 모두가 손에 든 카드가 공개되고, 모두가 가진 고양이 카드의 개수가 합산되어 가설이 맞는지 아닌지 세어볼 수 있습니다.
앞사람의 가설이 틀렸다면 그 사람이 게임에서 아웃되고, 가설이 맞았다면 의문을 제기한 사람이 아웃됩니다.
박사 학위 능력
이름-능력 순
Albert Felinestein 당신의 연구를 버리고 버린 만큼 다시 뽑을 수 있습니다.
Cecelia Pounce 이 연구에 살아있는 고양이 숫자 2마리를 더합니다.
Madam Purrie 공개되어 있는 살아있는 고양이 카드를 모두 버립니다.
Maria Goeppertmeower 이 연구에 빈 박스를 하나 더합니다.
Mittens Faraday 공개되어 있는 죽은 고양이 카드를 모두 버립니다.
Neil Degrasse Tabby 공개된 물리학자 카드의 효과를 복사합니다.
Sally Prride 이번 턴에 버려진 카드 더미를 확인할 수 있습니다.
Sir Isaac Mewton 연구 덱에서 추가로 2장의 카드를 뽑습니다.
Stephen Pawking 당신의 가설 세우기 단계를 패스합니다.
Whiskers Feyncat 이 연구에 하이젠베르크 카드 개수를 제외합니다.
7c70393fd8d32083f70bd085496d7bcfe3302575
1393
1379
2022-03-04T19:04:22Z
Producer Zenn
7863
wikitext
text/x-wiki
== 세팅 ==
a) 각 플레이어마다 한 장의 박사 카드가 지급되고 폐기 더미 안에 한 장의 박사 카드를 둡니다.
b) 각 플레이어에게 플레이어 수와 동일한 상자 수를 나누어 줍니다. (예: 플레이어 4명일 시 상자카드 4장)
c) 연구 덱을 세팅한다.
== 박스 카드 종류 ==
'''살아있는 고양이 카드'''
가장 낮은 랭크의 카드입니다. 총 20장이 덱에 들어있습니다.
'''죽은 고양이 카드'''
살아있는 고양이보다는 랭크가 높지만 빈 상자보다는 순위가 낮습니다.총 20장이 덱에 들어있습니다.
'''빈 박스'''
가장 높은 랭크의 카드입니다. 가설을 제시할 때 두 배의 가치를 지닙니다. 총 8장이 덱에 들어있습니다.
'''하이젠베르크'''
이것은 와일드 카드(조커)입니다. 이것은 항상 직전에 제시되었던 가설과 동일한 카드로 간주됩니다. 따라서 하이젠베르크를 가지고 가설을 세우는 것은 불가능합니다. 총 4장이 덱에 들어있습니다.
== 내 턴에 할 일 ==
a-1) 가설 배팅 패널에서 배팅을 합니다. 배팅이란, 나를 포함한 전원이 손에 들고 있는 패 중에 과연 '살아있는/죽은/빈' 카드가 모두 몇 장인지를 찍는 것입니다.
배팅을 할 때는 항상 직전에 제시된 가설보다 더 높은 랭크-즉, 오른쪽 또는 하단-으로만 상위입찰을 할 수 있습니다.
b) 그런 다음 현재 입찰과 일치하는 유형의 카드를 내려놓아 결과를 보여줄 수 있습니다.(보여주지 않아도 됩니다) ex)살아있는 고양이가 5마리 있다고 배팅했다면, 손에 든 카드 중 살아있는 고양이 카드를 한 장 공개할 수 있다.
그런 다음 원하는 만큼 손에 남은 상자(카드)를 버리고 버린 장수만큼 다시 가져올 수 있습니다.
c) 박사학위(고양이 물리학자 카드)를 공개할 수 있습니다. 이 경우 한번 사용하면 게임이 끝날 때까지 더이상의 박사학위 카드는 사용이 불가능합니다.
a-2) 만약 당신이 직전에 배팅한 사람의 가설이 거짓이라고 생각한다면 의문을 제기합니다.
그러면 모두가 손에 든 카드가 공개되고, 모두가 가진 고양이 카드의 개수가 합산되어 가설이 맞는지 아닌지 세어볼 수 있습니다.
앞사람의 가설이 틀렸다면 그 사람이 게임에서 아웃되고, 가설이 맞았다면 의문을 제기한 사람이 아웃됩니다.
== 박사 학위 능력 ==
이름-능력 순
Albert Felinestein 당신의 연구를 버리고 버린 만큼 다시 뽑을 수 있습니다.
Cecelia Pounce 이 연구에 살아있는 고양이 숫자 2마리를 더합니다.
Madam Purrie 공개되어 있는 살아있는 고양이 카드를 모두 버립니다.
Maria Goeppertmeower 이 연구에 빈 박스를 하나 더합니다.
Mittens Faraday 공개되어 있는 죽은 고양이 카드를 모두 버립니다.
Neil Degrasse Tabby 공개된 물리학자 카드의 효과를 복사합니다.
Sally Prride 이번 턴에 버려진 카드 더미를 확인할 수 있습니다.
Sir Isaac Mewton 연구 덱에서 추가로 2장의 카드를 뽑습니다.
Stephen Pawking 당신의 가설 세우기 단계를 패스합니다.
Whiskers Feyncat 이 연구에 하이젠베르크 카드 개수를 제외합니다.
945cce6827aaf4049d93fbf60303dd7805e009f3
1394
1393
2022-03-04T19:05:12Z
Producer Zenn
7863
wikitext
text/x-wiki
== 세팅 ==
a) 각 플레이어마다 한 장의 박사 카드가 지급되고 폐기 더미 안에 한 장의 박사 카드를 둡니다.
b) 각 플레이어에게 플레이어 수와 동일한 상자 수를 나누어 줍니다. (예: 플레이어 4명일 시 상자카드 4장)
c) 연구 덱을 세팅한다.
== 박스 카드 종류 ==
'''살아있는 고양이 카드'''
가장 낮은 랭크의 카드입니다. 총 20장이 덱에 들어있습니다.
'''죽은 고양이 카드'''
살아있는 고양이보다는 랭크가 높지만 빈 상자보다는 순위가 낮습니다.총 20장이 덱에 들어있습니다.
'''빈 박스'''
가장 높은 랭크의 카드입니다. 가설을 제시할 때 두 배의 가치를 지닙니다. 총 8장이 덱에 들어있습니다.
'''하이젠베르크'''
이것은 와일드 카드(조커)입니다. 이것은 항상 직전에 제시되었던 가설과 동일한 카드로 간주됩니다. 따라서 하이젠베르크를 가지고 가설을 세우는 것은 불가능합니다. 총 4장이 덱에 들어있습니다.
== 내 턴에 할 일 ==
a-1) 가설 배팅 패널에서 배팅을 합니다. 배팅이란, '''나를 포함한 전원이 손에 들고 있는 패 중에 과연 '살아있는/죽은/빈' 카드가 모두 몇 장인지를 찍는 것'''입니다.
배팅을 할 때는 '''항상 직전에 제시된 가설보다 더 높은 랭크-즉, 오른쪽 또는 하단-으로만 상위입찰'''을 할 수 있습니다.
b) 그런 다음 현재 입찰과 일치하는 유형의 카드를 내려놓아 결과를 보여줄 수 있습니다.(보여주지 않아도 됩니다) ex)살아있는 고양이가 5마리 있다고 배팅했다면, 손에 든 카드 중 살아있는 고양이 카드를 한 장 공개할 수 있다.
그런 다음 공개한 카드 장수 만큼 손에 남은 카드를 버리고 버린 장수만큼 다시 가져올 수 있습니다.
c) 박사학위(고양이 물리학자 카드)를 공개할 수 있습니다. 이 경우 한번 사용하면 게임이 끝날 때까지 더이상의 박사학위 카드는 사용이 불가능합니다.
a-2) 만약 당신이 직전에 배팅한 사람의 가설이 거짓이라고 생각한다면 의문을 제기합니다.
그러면 모두가 손에 든 카드가 공개되고, 모두가 가진 고양이 카드의 개수가 합산되어 가설이 맞는지 아닌지 세어볼 수 있습니다.
앞사람의 가설이 틀렸다면 그 사람이 게임에서 아웃되고, 가설이 맞았다면 의문을 제기한 사람이 아웃됩니다.
== 박사 학위 능력 ==
이름-능력 순
Albert Felinestein 당신의 연구를 버리고 버린 만큼 다시 뽑을 수 있습니다.
Cecelia Pounce 이 연구에 살아있는 고양이 숫자 2마리를 더합니다.
Madam Purrie 공개되어 있는 살아있는 고양이 카드를 모두 버립니다.
Maria Goeppertmeower 이 연구에 빈 박스를 하나 더합니다.
Mittens Faraday 공개되어 있는 죽은 고양이 카드를 모두 버립니다.
Neil Degrasse Tabby 공개된 물리학자 카드의 효과를 복사합니다.
Sally Prride 이번 턴에 버려진 카드 더미를 확인할 수 있습니다.
Sir Isaac Mewton 연구 덱에서 추가로 2장의 카드를 뽑습니다.
Stephen Pawking 당신의 가설 세우기 단계를 패스합니다.
Whiskers Feyncat 이 연구에 하이젠베르크 카드 개수를 제외합니다.
9b932aa12f5774ada7681f350686b7d810d552f3
1401
1394
2022-03-16T08:23:36Z
Kor yong
7827
/* 박스 카드 종류 */
wikitext
text/x-wiki
== 세팅 ==
a) 각 플레이어마다 한 장의 박사 카드가 지급되고 폐기 더미 안에 한 장의 박사 카드를 둡니다.
b) 각 플레이어에게 플레이어 수와 동일한 상자 수를 나누어 줍니다. (예: 플레이어 4명일 시 상자카드 4장)
c) 연구 덱을 세팅한다.
== 박스 카드 종류 ==
'''살아있는 고양이 카드'''
가장 낮은 랭크의 카드입니다. 총 20장이 덱에 들어있습니다.
'''죽은 고양이 카드'''
살아있는 고양이보다는 랭크가 높지만 빈 상자보다는 순위가 낮습니다.총 20장이 덱에 들어있습니다.
'''빈 박스'''
가장 높은 랭크의 카드입니다. 가설을 제시할 때 두 배의 가치를 지닙니다. 총 8장이 덱에 들어있습니다.
예)가치 : 살아있는 2장<죽은 2장<빈 1장
'''하이젠베르크'''
이것은 와일드 카드(조커)입니다. 이것은 항상 직전에 제시되었던 가설과 동일한 카드로 간주됩니다. 따라서 하이젠베르크를 가지고 가설을 세우는 것은 불가능합니다. 총 4장이 덱에 들어있습니다.
== 내 턴에 할 일 ==
a-1) 가설 배팅 패널에서 배팅을 합니다. 배팅이란, '''나를 포함한 전원이 손에 들고 있는 패 중에 과연 '살아있는/죽은/빈' 카드가 모두 몇 장인지를 찍는 것'''입니다.
배팅을 할 때는 '''항상 직전에 제시된 가설보다 더 높은 랭크-즉, 오른쪽 또는 하단-으로만 상위입찰'''을 할 수 있습니다.
b) 그런 다음 현재 입찰과 일치하는 유형의 카드를 내려놓아 결과를 보여줄 수 있습니다.(보여주지 않아도 됩니다) ex)살아있는 고양이가 5마리 있다고 배팅했다면, 손에 든 카드 중 살아있는 고양이 카드를 한 장 공개할 수 있다.
그런 다음 공개한 카드 장수 만큼 손에 남은 카드를 버리고 버린 장수만큼 다시 가져올 수 있습니다.
c) 박사학위(고양이 물리학자 카드)를 공개할 수 있습니다. 이 경우 한번 사용하면 게임이 끝날 때까지 더이상의 박사학위 카드는 사용이 불가능합니다.
a-2) 만약 당신이 직전에 배팅한 사람의 가설이 거짓이라고 생각한다면 의문을 제기합니다.
그러면 모두가 손에 든 카드가 공개되고, 모두가 가진 고양이 카드의 개수가 합산되어 가설이 맞는지 아닌지 세어볼 수 있습니다.
앞사람의 가설이 틀렸다면 그 사람이 게임에서 아웃되고, 가설이 맞았다면 의문을 제기한 사람이 아웃됩니다.
== 박사 학위 능력 ==
이름-능력 순
Albert Felinestein 당신의 연구를 버리고 버린 만큼 다시 뽑을 수 있습니다.
Cecelia Pounce 이 연구에 살아있는 고양이 숫자 2마리를 더합니다.
Madam Purrie 공개되어 있는 살아있는 고양이 카드를 모두 버립니다.
Maria Goeppertmeower 이 연구에 빈 박스를 하나 더합니다.
Mittens Faraday 공개되어 있는 죽은 고양이 카드를 모두 버립니다.
Neil Degrasse Tabby 공개된 물리학자 카드의 효과를 복사합니다.
Sally Prride 이번 턴에 버려진 카드 더미를 확인할 수 있습니다.
Sir Isaac Mewton 연구 덱에서 추가로 2장의 카드를 뽑습니다.
Stephen Pawking 당신의 가설 세우기 단계를 패스합니다.
Whiskers Feyncat 이 연구에 하이젠베르크 카드 개수를 제외합니다.
4b8ac1a809e1a6f73d55e02ff1f6475729b4b3c7
Gamehelpbutterfly
0
221
1380
2022-02-01T20:20:29Z
Producer Zenn
7863
새 문서: Butterfly는 리오 그란데의 간단한 타일 세트 수집 게임입니다. 고슴도치를 타일에서 타일로 옮겨가며 점수를 얻을 수 있습니다. ★게임플...
wikitext
text/x-wiki
Butterfly는 리오 그란데의 간단한 타일 세트 수집 게임입니다. 고슴도치를 타일에서 타일로 옮겨가며 점수를 얻을 수 있습니다.
★게임플레이
1. 출발 선수 왼쪽에 있는 플레이어가 고슴도치를 아무 타일 위에 올려놓습니다.
2.그리고 나서 플레이어들은 순서대로 진행한다. 자신의 차례가 되면 여러분은 고슴도치를 그것의 앞, 왼쪽 또는 오른쪽 일직선에 있는 아무 타일로나 옮기고, 고슴도치가 움직이는 방향으로 고슴도치 조각을 회전시킵니다.
움직일 수 있는 방향에 타일 개수가 한정되어 있다면 반드시 그것을 수집해야 합니다.
빈 공간은 무시하고 목표 타일로 직진할 수 있습니다. 당신이 타일 위에 멈추면, 그것을 모읍니다.
보드의 몇몇 군데에는 잠자리채가 있어 타일을 모으다 보면 드러납니다. 고슴도치가 이동하다가 노출된 잠자리채 위로 지나가면 플레이어는 즉시 덱에서 무작위로 타일을 뽑아 덱으로 가져와 점수에 포함시킵니다.
★ 점수
나비 : 타일에 표시된 점수가 점수입니다. (색깔별로 점수를 곱하는 x2 타일도 존재)
잠자리 : 수집된 잠자리 중 가장 높은 것만 채점합니다.
반딧불 : 수집된 반딧불 중 가장 낮은 타일의 점수만을 매깁니다.
메뚜기 : 마지막으로 수집한 메뚜기만 채점하며 이전 타일은 버립니다.
꽃 : 각각 채집한 꽃의 제곱수만큼 가치가 있습니다(예: 꽃이 4개인 경우 꽃 한 송이당 4점 = 총 16점).
벌 : 벌만 있으면 -3점, 세트가 되는 벌집이 존재하면 0점
벌집 : 벌집만 있으면 0점, 세트가 되는 벌이 한 마리 있으면 표기된 점수
★ 게임 종료
고슴도치가 더 이상 움직일 수 없을 때 게임은 끝납니다. 그때 가장 높은 점수를 받은 플레이어가 승리합니다!
460d6706f2841ccf597e629fc6557e7badecb2c9
Gamehelpskull
0
222
1381
2022-02-02T15:41:30Z
Producer Zenn
7863
새 문서: 각 플레이어는 꽃 3송이와 해골 1개가 그려진 원판을 받는다. 매트는 해골이 그려진 면이 위를 향한 상태이다. 각 플레이어는 매트 위에...
wikitext
text/x-wiki
각 플레이어는 꽃 3송이와 해골 1개가 그려진 원판을 받는다.
매트는 해골이 그려진 면이 위를 향한 상태이다.
각 플레이어는 매트 위에 4장의 원판 중 하나를 하나 골라 엎어 놓는다.
그런 다음 첫 번째 플레이어부터 원판을 더 뒤집을지 여부를 선택한다. 만약 원판을 추가하고 싶지 않다면, 도전과 입찰을 해야 한다.
도전이 시작되면, 플레이어는 입찰가를 높이거나(매트에 놓인 모든 뒤집어진 원판 개수까지) 패스를 할 수 있다. 모두가 패스를 하고 가장 높이 입찰가를 부른 입찰자가 도전자가 된다.
도전자는 자신이 입찰한 것과 같은 수만큼의 원판을 뒤집어야 한다. 처음에는 자신의 디스크를 모두 뒤집은 다음 다른 플레이어가 뒤집은 원판을 골라 위부터 뒤집는다.
원판을 뒤집다가 해골이 나오면 도전자는 원판을 하나 잃는다. 도전자가 마지막 원판을 잃으면 탈락한다.
입찰한 개수만큼 꽃이 그려진 원판을 모두 뒤집으면 꽃이 그려진 면으로 매트를 뒤집는다.(1 포인트 획득).
2포인트를 획득한 사람이 먼저 이긴다.
c8d5baecd4d36cba005a660a90841d0be34d075f
Gamehelpnarabi
0
223
1382
2022-02-02T22:22:00Z
Ufm
6353
새 문서: == 개요 == 여러분은 신비한 정원의 돌들을 올바른 순서대로 늘어세워야 합니다. 하지만 돌에는 정원의 마법이 걸려 있어, 저마다 특별한...
wikitext
text/x-wiki
== 개요 ==
여러분은 신비한 정원의 돌들을 올바른 순서대로 늘어세워야 합니다.
하지만 돌에는 정원의 마법이 걸려 있어, 저마다 특별한 조건을 따르지 않으면 움직일 수 없습니다!
다른 사람들과 협력해서 아름다운 정원에 걸린 마법을 풀어 보세요.
== 준비 ==
조건 카드와 돌 카드를 따로 섞은 뒤 각각 한쪽 면만 보이도록 무작위로 슬리브에 끼웁니다. 이 과정에서 조건 카드를 확인할 수는 없습니다!
3 ~ 4인 게임에서는 번호가 없는 흰 돌 하나, 번호가 없는 검은 돌 하나, 9번 돌을 뺍니다.
카드를 섞어 돌 카드가 보이도록 나눠줍니다. 3인에서는 4장씩, 4 ~ 5인에서는 3장씩 받습니다.
받은 카드의 순서를 바꿀 수는 없습니다.
0번 카드를 받은 사람이 게임을 시작합니다.
== 게임 진행 ==
자기 차례에는 자기 돌 하나를 골라 그 카드의 조건에 맞게 다른 사람의 돌 하나와 맞바꿔야 합니다. 자기 돌 2개를 맞바꿀 수는 없습니다.
(맞바꿔서 새로 받은 카드를 포함하여) 자기 카드의 조건은 언제든지 확인할 수 있지만 알려줄 수는 없습니다.
하지만 조건 카드를 알려주지 않는 범위 내에서라면 전략이나 앞으로 어떻게 할지 물어보거나 '네', '아니요'로 대답할 수 있습니다.
돌을 바꾼 뒤에는 차례가 시계방향으로 넘어갑니다.
'''참고: 숫자가 없는 돌은 조건에서 0과 짝수로 취급하지만, 숫자를 올바르게 늘어놓았는지 판별할 때는 제외됩니다. 아래를 참고하세요.'''
== 게임 종료 ==
모든 카드가 (시계방향이나 반시계방향으로) 순서대로 늘어섰다면 모두의 승리입니다. 숫자가 없는 돌은 순서에서 계산하지 않습니다.
24번의 차례가 끝났어도 돌이 아직 순서대로 늘어서지 않았거나, 자기 차레에 돌을 다른 사람과 맞바꿀 수 없다면 모두 패배합니다.
== 상급 난이도 ==
상급 난이도에서는 이전 차례에 맞바꾼 돌을 다시 직전의 위치로 되돌릴 수 없으며, 서로 대화할 수 없습니다.
== ELO / 레이팅 ==
보드게임 아레나의 나라비는 정상적으로 종료된 게임에서 절대 레이팅이 감소하지 않습니다.
게임에서 승리하면 점수만큼 ELO가 증가합니다 (예를 들어 돌을 10번 맞바꾸고 승리했다면 ELO가 +15 증가합니다).
4 ~ 5인과 상급 난이도에서는 추가로 ELO가 증가합니다. 3명을 넘는 인원수마다 +5, 상급 난이도에서는 +5가 더 증가합니다.
== 플레이어 설정 옵션 ==
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
=== 조건 카드 목록 표시 ===
* '''네''': 게임 화면 아래에 모든 조건 카드를 표시합니다. 3~4인에서 무작위로 빠지는 카드 3장도 함께 표시합니다.
* 아니요: 조건 카드 목록을 숨깁니다.
=== 점수 카드 표시 ===
* '''네''': 게임판 중앙에 점수 카드와 점수 표지를 표시합니다.
* 아니요: 점수 카드와 점수 표지를 숨깁니다.
=== 조건 카드 글꼴 ===
* '''테마풍''': 조건 카드에 테마풍 글꼴을 사용합니다.
* BGA 기본: BGA 기본 글꼴을 사용합니다.
39545ed6ba3e912b76efee6f4e9c7df4b08a809b
1385
1382
2022-02-06T02:04:12Z
Ufm
6353
/* 플레이어 설정 옵션 */
wikitext
text/x-wiki
== 개요 ==
여러분은 신비한 정원의 돌들을 올바른 순서대로 늘어세워야 합니다.
하지만 돌에는 정원의 마법이 걸려 있어, 저마다 특별한 조건을 따르지 않으면 움직일 수 없습니다!
다른 사람들과 협력해서 아름다운 정원에 걸린 마법을 풀어 보세요.
== 준비 ==
조건 카드와 돌 카드를 따로 섞은 뒤 각각 한쪽 면만 보이도록 무작위로 슬리브에 끼웁니다. 이 과정에서 조건 카드를 확인할 수는 없습니다!
3 ~ 4인 게임에서는 번호가 없는 흰 돌 하나, 번호가 없는 검은 돌 하나, 9번 돌을 뺍니다.
카드를 섞어 돌 카드가 보이도록 나눠줍니다. 3인에서는 4장씩, 4 ~ 5인에서는 3장씩 받습니다.
받은 카드의 순서를 바꿀 수는 없습니다.
0번 카드를 받은 사람이 게임을 시작합니다.
== 게임 진행 ==
자기 차례에는 자기 돌 하나를 골라 그 카드의 조건에 맞게 다른 사람의 돌 하나와 맞바꿔야 합니다. 자기 돌 2개를 맞바꿀 수는 없습니다.
(맞바꿔서 새로 받은 카드를 포함하여) 자기 카드의 조건은 언제든지 확인할 수 있지만 알려줄 수는 없습니다.
하지만 조건 카드를 알려주지 않는 범위 내에서라면 전략이나 앞으로 어떻게 할지 물어보거나 '네', '아니요'로 대답할 수 있습니다.
돌을 바꾼 뒤에는 차례가 시계방향으로 넘어갑니다.
'''참고: 숫자가 없는 돌은 조건에서 0과 짝수로 취급하지만, 숫자를 올바르게 늘어놓았는지 판별할 때는 제외됩니다. 아래를 참고하세요.'''
== 게임 종료 ==
모든 카드가 (시계방향이나 반시계방향으로) 순서대로 늘어섰다면 모두의 승리입니다. 숫자가 없는 돌은 순서에서 계산하지 않습니다.
24번의 차례가 끝났어도 돌이 아직 순서대로 늘어서지 않았거나, 자기 차레에 돌을 다른 사람과 맞바꿀 수 없다면 모두 패배합니다.
== 상급 난이도 ==
상급 난이도에서는 이전 차례에 맞바꾼 돌을 다시 직전의 위치로 되돌릴 수 없으며, 서로 대화할 수 없습니다.
== ELO / 레이팅 ==
보드게임 아레나의 나라비는 정상적으로 종료된 게임에서 절대 레이팅이 감소하지 않습니다.
게임에서 승리하면 점수만큼 ELO가 증가합니다 (예를 들어 돌을 10번 맞바꾸고 승리했다면 ELO가 +15 증가합니다).
4 ~ 5인과 상급 난이도에서는 추가로 ELO가 증가합니다. 3명을 넘는 인원수마다 +5, 상급 난이도에서는 +5가 더 증가합니다.
== 플레이어 설정 옵션 ==
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
=== 조건 카드 목록 표시 ===
* '''네''': 게임 화면 아래에 모든 조건 카드를 표시합니다. 3~4인에서 무작위로 빠지는 카드 3장도 함께 표시합니다.
* 아니요: 조건 카드 목록을 숨깁니다.
=== 점수 카드 표시 ===
* '''네''': 게임판 중앙에 점수 카드와 점수 표지를 표시합니다.
* 아니요: 점수 카드와 점수 표지를 숨깁니다.
=== 조건 카드 글꼴 ===
* '''테마풍''': 조건 카드에 테마풍 글꼴을 사용합니다.
* BGA 기본: BGA 기본 글꼴을 사용합니다.
=== 바꿀 수 없는 돌은 반투명 표시 ===
* '''네''': 차례를 진행하는 플레이어가 자기 돌을 고르면, 그 돌과 맞바꿀 수 없는 다른 사람의 돌을 반투명하게 표시합니다. 핫시트 모드의 가상 계정에서는 적용되지 않습니다.
* 아니요: 카드에 반투명 표시를 하지 않습니다.
d64e6d52e8217b2591136cb800c484508a137001
1386
1385
2022-02-06T03:37:21Z
Ufm
6353
/* 플레이어 설정 옵션 */
wikitext
text/x-wiki
== 개요 ==
여러분은 신비한 정원의 돌들을 올바른 순서대로 늘어세워야 합니다.
하지만 돌에는 정원의 마법이 걸려 있어, 저마다 특별한 조건을 따르지 않으면 움직일 수 없습니다!
다른 사람들과 협력해서 아름다운 정원에 걸린 마법을 풀어 보세요.
== 준비 ==
조건 카드와 돌 카드를 따로 섞은 뒤 각각 한쪽 면만 보이도록 무작위로 슬리브에 끼웁니다. 이 과정에서 조건 카드를 확인할 수는 없습니다!
3 ~ 4인 게임에서는 번호가 없는 흰 돌 하나, 번호가 없는 검은 돌 하나, 9번 돌을 뺍니다.
카드를 섞어 돌 카드가 보이도록 나눠줍니다. 3인에서는 4장씩, 4 ~ 5인에서는 3장씩 받습니다.
받은 카드의 순서를 바꿀 수는 없습니다.
0번 카드를 받은 사람이 게임을 시작합니다.
== 게임 진행 ==
자기 차례에는 자기 돌 하나를 골라 그 카드의 조건에 맞게 다른 사람의 돌 하나와 맞바꿔야 합니다. 자기 돌 2개를 맞바꿀 수는 없습니다.
(맞바꿔서 새로 받은 카드를 포함하여) 자기 카드의 조건은 언제든지 확인할 수 있지만 알려줄 수는 없습니다.
하지만 조건 카드를 알려주지 않는 범위 내에서라면 전략이나 앞으로 어떻게 할지 물어보거나 '네', '아니요'로 대답할 수 있습니다.
돌을 바꾼 뒤에는 차례가 시계방향으로 넘어갑니다.
'''참고: 숫자가 없는 돌은 조건에서 0과 짝수로 취급하지만, 숫자를 올바르게 늘어놓았는지 판별할 때는 제외됩니다. 아래를 참고하세요.'''
== 게임 종료 ==
모든 카드가 (시계방향이나 반시계방향으로) 순서대로 늘어섰다면 모두의 승리입니다. 숫자가 없는 돌은 순서에서 계산하지 않습니다.
24번의 차례가 끝났어도 돌이 아직 순서대로 늘어서지 않았거나, 자기 차레에 돌을 다른 사람과 맞바꿀 수 없다면 모두 패배합니다.
== 상급 난이도 ==
상급 난이도에서는 이전 차례에 맞바꾼 돌을 다시 직전의 위치로 되돌릴 수 없으며, 서로 대화할 수 없습니다.
== ELO / 레이팅 ==
보드게임 아레나의 나라비는 정상적으로 종료된 게임에서 절대 레이팅이 감소하지 않습니다.
게임에서 승리하면 점수만큼 ELO가 증가합니다 (예를 들어 돌을 10번 맞바꾸고 승리했다면 ELO가 +15 증가합니다).
4 ~ 5인과 상급 난이도에서는 추가로 ELO가 증가합니다. 3명을 넘는 인원수마다 +5, 상급 난이도에서는 +5가 더 증가합니다.
== 플레이어 설정 옵션 ==
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
=== 조건 카드 목록 표시 ===
* '''네''': 게임 화면 아래에 모든 조건 카드를 표시합니다. 3~4인에서 무작위로 빠지는 카드 3장도 함께 표시합니다.
* 아니요: 조건 카드 목록을 숨깁니다.
=== 점수 카드 표시 ===
* '''네''': 게임판 중앙에 점수 카드와 점수 표지를 표시합니다.
* 아니요: 점수 카드와 점수 표지를 숨깁니다.
=== 조건 카드 글꼴 ===
* '''테마풍''': 조건 카드에 테마풍 글꼴을 사용합니다.
* BGA 기본: BGA 기본 글꼴을 사용합니다.
=== 바꿀 수 없는 돌은 반투명 표시 ===
* '''네''': 차례를 진행하는 플레이어가 자기 돌을 고르면, 그 돌과 맞바꿀 수 없는 다른 사람의 돌을 반투명하게 표시합니다. 핫시트 모드의 가상 계정에서는 적용되지 않습니다.
* 아니요: 카드에 반투명 표시를 하지 않습니다.
=== 배경 ===
* '''테마풍''': 테마에 어울리는 배경 화면을 사용합니다.
* BGA 기본: BGA 기본 배경 화면을 사용합니다.
c8c61a4d43e0f4cd33ca9e26f40d24aa124c3665
Tips splendor
0
224
1383
2022-02-05T13:53:25Z
Tina113
7877
새 문서: 보드게임 아레나를 위한 설명서입니다. 온라인으로 보드게임을 즐겨보세요!
wikitext
text/x-wiki
보드게임 아레나를 위한 설명서입니다. 온라인으로 보드게임을 즐겨보세요!
e57ed6a87810225ddaccabe644174d00abda5917
1384
1383
2022-02-05T13:55:15Z
Tina113
7877
문서를 비움
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelptumbleweed
0
210
1387
1350
2022-02-09T05:13:13Z
Ufm
6353
wikitext
text/x-wiki
== 게임 설명 ==
텀블위드는 정육각형 헥스 게임판에서 말 더미를 쌓는 2인 게임입니다.
게임판에 놓인 더미는 서로 직선으로 이어졌으며 그 더미와 칸 사이에 다른 더미가 없는 칸을 '볼' 수 있습니다. 각자 번갈아 자기 더미가 볼 수 있는 칸에 더미를 놓습니다. 새로 놓는 더미의 높이는 그 더미를 볼 수 있는 자기 더미의 수와 같습니다. 상대 더미를 잡거나 자기 더미를 강화해 이미 놓인 더미를 더 높은 새 더미로 교체할 수도 있습니다.
게임을 시작하기 전에 선공이 게임판의 초기 배치를 결정한 뒤 후공이 어느 색깔로 게임을 진행할지 결정합니다. 초기 배치 단계에는 중립 말 2개가 쌓인 더미 하나와, 선공이 원하는 위치에 놓는 각 플레이어의 시작 토큰 하나를 배치합니다.
두 플레이어 모두 더 이상 수를 둘 수 없거나 두 명이 연속으로 차례를 넘기면 게임이 끝납니다. 더 많은 칸을 차지한 플레이어가 승리합니다.
텀블위드는 보드게임긱에서 2020년에 최고의 2인 조합 게임으로 뽑혔습니다.
이 설명은 보드게임긱의 텀블위드 페이지에서 가져왔습니다.
== 게임 종료 알림 ==
양쪽 플레이어 모두 3번의 차례 동안 상대 더미를 잡거나 통제하는 칸을 공격하지 않으면 알림이 표시됩니다.
이 상태가 앞으로 각자 1번씩 더 계속되면 게임이 자동으로 끝납니다.
각자의 영역이 확정되었다면 서로 차례를 넘겨 게임을 마치기를 권장합니다.
== 설정 ==
보드게임 아레나 버전에서는 새로운 변형규칙과 플레이어 옵션을 지원합니다.
'''기본 옵션은 볼드체로 표기했습니다.'''
=== 게임판 크기 ===
* '''6x6x6''': 가장 작은 크기의 게임판입니다. 초보자나 속기전에 추천합니다.
* 8x8x8: 경쟁전용 표준 게임판입니다.
* 10x10x10: 더 큰 크기의 게임판입니다. 턴 기반 게임이나 복잡한 게임에 추천합니다.
* 11x11x11: 가장 큰 크기의 게임판입니다. 턴 기반 게임이나 깊이 있는 게임에 추천합니다.
=== 초기 배치 ===
* '''기본 설정''': 중립 더미를 중앙에 놓습니다.
* 자유 설정: 게임 시작 시의 선공이 중립 더미를 놓습니다.
=== 플레이어 보조 기능 ===
* 초보자: 게임 중에 표시되는 점수는 더미를 놓아 점유한 칸과 지배하고 있는 빈칸의 수를 합쳐서 보여줍니다. 지배한 칸은 강조 표시, 더미를 잡는 자충수가 아닌 수는 테두리로 표시합니다. 둔 수를 확인할 때, 상대가 바로 잡을 수 있는 더미는 회색으로 표시합니다.
통제하고 있는 칸과 잡을 수 있는 더미의 강조 표시는 플레이어 설정 옵션으로 켜고 끌 수 있습니다.
* '''중급자''': 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸과 통제하고 있는 빈칸의 수를 합쳐서 보여줍니다. 둔 수를 확인할 때, 상대가 바로 잡을 수 있는 더미는 회색으로 표시합니다.
* 전문가: 게임 중에 표시되는 점수는 더미를 놓아 차지한 칸만 계산합니다. 통제하고 있는 빈칸의 수는 게임이 끝날 때에 보여줍니다. 둔 수를 확인할 때에는 놓이는 더미의 색깔만 표시합니다.
현실의 게임처럼 진행됩니다.
=== 플레이어 설정 옵션 ===
우상단 메뉴를 누르거나 게임 화면 아래의 설정 탭을 눌러 바꿀 수 있습니다.
==== 확인 표시 ====
* '''활성화''': 육각형 칸을 누르면 놓을 더미를 미리 볼 수 있습니다. 미리보기 더미를 다시 눌러야 둔 수가 확정됩니다.
* 비활성화: 칸을 누르면 미리보기 없이 바로 더미를 놓습니다.
전문가 모드에서는 미리보기에서 놓을 더미의 색깔만 표시합니다.
==== 마지막 수 강조 ====
* '''활성화''': 노란색 톤으로 마지막 수를 강조 표시합니다.
* 비활성화: 마지막 수를 강조하지 않습니다.
==== 좌표 표시 ====
* '''활성화''': 게임판 주변에 좌표를 표시합니다.
* 비활성화: 게임판 주변의 좌표를 표시하지 않습니다.
==== 영향력 표시 (초보자 모드 한정) ====
* '''활성화''': 통제 상태의 칸은 통제한 플레이어의 색깔로 표시합니다. 분홍색 칸은 두 플레이어의 영향력이 같은 칸입니다.
* 비활성화: 빈칸의 영향력을 표시하지 않습니다.
이 옵션은 중급자와 전문가 모드에서는 아무 효과가 없습니다.
==== 더미를 잡는 자충수가 아닌 수 강조 (초보자 모드 한정) ====
* '''활성화''': 잡을 수 있는 더미의 테두리 색깔이 바뀝니다. 상대가 잡을 수 있는 더미의 색깔만 바뀌며, 자충수가 되는 수이거나 강화만 할 수 있는 더미는 그대로입니다.
* 비활성화: 잡을 수 있는 더미의 색깔이 바뀌지 않습니다.
이 옵션은 중급자와 전문가 모드에서는 아무 효과가 없습니다.
f0abe587f39b2f7a82060f46df18676071b09a71
Gamehelpgaiaproject
0
225
1388
2022-02-13T18:27:38Z
Qwqwqw468316
7903
새 문서: 보드게임 아레나: 이 페이지는 보드게임 아레나 관련 페이지입니다.
wikitext
text/x-wiki
보드게임 아레나:
이 페이지는 보드게임 아레나
관련 페이지입니다.
6358d4212772a05ba6215bc80c787006ceae285f
Gamehelpyatzy
0
122
1389
1243
2022-02-20T05:48:10Z
Jjdy2435
7919
wikitext
text/x-wiki
야찌는 13라운드로 이루어져 있습니다. 각각의 라운드에, 당신은 5개의 주사위들을 굴린 후에 당신의 선택에 따라서 다른 범위에 점수를 적습니다.
한 라운드 동안에, 당신은 그 주사위들을 점수를 적기 전에 3번 까지 굴릴 수 있습니다. - 첫번째 굴림 (당신이 모든 주사위를 굴려야 하는), 일부나 모든 주사위를 추가적으로 최대 2번까지 굴림.
13개의 점수 범위들이 있고, 각각은 13라운드에 1개가 사용되어져야 합니다. 따라서 종종 몇몇의 범위에는 0점이 되기도 합니다.
13개의 점수 범위들은 다음과 같습니다 :
1-6: 주사위의 각각의 수에 대해서 1개의 범위가 있습니다. 이 범위에서는, 점수는 주사위의 해당 숫자의 눈금의 합으로 매겨집니다. 예를들어서, 1-1-2-5-5의 굴림은 "1" 범위에서 2점으로 메겨질 수 있고, "2" 범주에서는 2점, "5"범위에서는 10점으로, "3, 4, 6"에는 0점으로 메겨질 수 있습니다. 만약 한 플레이어가 이러한 6개의 범위에서 총합이 63점 이상이라면, 보너스 35점이 추가됩니다.
7. 같은 종류 3개 : 같은 면을 보여주는 최소한 3개의 주사위들 - 모든 5개의 주사위들의 총 합과 같은 점수 (한 종류의 3개의 점수만이 아니라)
8. 같은 종류 4개 : 같은 면을 보여주는 최소한 4개의 주사위들 - 모든 5개의 주사위들의 총 합과 같은 점수 (한 종류의 4개의 점수만이 아니라)
9. 풀하우스 : 한 종류 3개와 한 종류 2개 - 25점
10. 스몰 스트레이트 : 4개의 순차적인 주사위들 (1-2-3-4, 2-3-4-5, 3-4-5-6) - 30점
11. 라지 스트레이트 : 5개의 순차적인 주사위들 (1-2-3-4-5, 2-3-4-5-6) - 40점
12. 야찌 : 같은 면을 보여주는 모든 5개의 주사위들 - 50점 (추가로, 첫번째 야찌에 50점을 획득하고, 2번째 야찌는 보너스 100점을 줍니다)
13. 찬스 : 아무 조합이나 - 5개의 주사위의 합과 같은 점수
9c6984ef14543ebb31be0f279ac446b38ca9105e
Tips castlesofburgundy
0
226
1390
2022-03-04T08:14:45Z
Daysofjuly
7953
새 문서: (영어 버전을 번역하며 설명을 추가했습니다.) 이 게임의 주 점수원은 영역을 완성해서 얻는 완료 점수입니다. 게임 초반에는 작은 영역...
wikitext
text/x-wiki
(영어 버전을 번역하며 설명을 추가했습니다.)
이 게임의 주 점수원은 영역을 완성해서 얻는 완료 점수입니다.
게임 초반에는 작은 영역을 완성하는 데 집중하고, 큰 영역은 게임 후반에 완성하세요. 대체로 인접한 보드판 타일은 5종 정도가 되기 때문에, 그중 4개 정도는 다 채운다고 생각하시고 작은 영역부터 시작해서 큰 영역을 채워 나간다는 느낌으로 진행하시면 좋습니다.
이 방법의 핵심은 주변에 놓을 수 있는 타일의 주사위 눈이 다양할수록 전략을 유동적으로 가져갈 수 있다는 것입니다.
(가령 인접한 타일의 눈이 2,2,3,3,5 인것보다는 1,2,3,4,5인 쪽이 더 다양한 경우의 수에 대응할 수 있겠지요.)
e0b2697d8ed98c0e2314bb4590d5c88a4ac5884c
Gamehelptranquility
0
227
1391
2022-03-04T19:01:52Z
Producer Zenn
7863
새 문서: == 1. 요약 == 당신은 트랭퀼리티 호를 타고 낙원 섬을 찾으려고 합니다. 그를 위해 전체 6x6 바다 격자를 1-80번으로 표시된 섬 카드(시작 카...
wikitext
text/x-wiki
== 1. 요약 ==
당신은 트랭퀼리티 호를 타고 낙원 섬을 찾으려고 합니다. 그를 위해 전체 6x6 바다 격자를 1-80번으로 표시된 섬 카드(시작 카드와 결승 카드 한 장)로 채워야 합니다. 격자를 완성하고 시작과 결승 카드를 놓아 섬의 낙원에서 하루를 보내게 된다면 모두 승리할 수 있습니다. 한 명의 플레이어가 더 이상 플레이를 할 수 없거나 카드를 더이상 버릴 수 없을 경우(섹션 4 참조) 영원히 길을 잃게 됩니다.
== 2. 플레이 개요 ==
시작 카드에 대해 논의할 때를 제외하고는 '''다른 플레이어와 의사소통을 할 수 없습니다'''(아래 참조).
한 명씩 돌아가면서 첫 번째 플레이어부터 시작해서 시계방향으로 테이블을 돌게 됩니다. 게임이 이기거나 질 때까지 이런 방식으로 플레이가 계속된다. 다음 작업 중 하나를 수행하여 작업을 수행해야 합니다.
'''A) 카드를 격자에 내려놓거나'''
'''B) 카드를 두장 버리기'''
행동이 끝나면 자신의 개별 덱에서, 줄어든 만큼 카드를 보충해 5장을 채우고 다음 사람으로 넘어가게 됩니다.
== 3. 상세 설명 ==
=== ㄱ.카드 내려놓기 ===
카드를 손에서 선택하고 다음 규칙을 따른다면 그리드의 아무 곳에서나 재생할 수 있습니다.
1. 카드는 '''왼쪽 아래에서 오른쪽 위로 오름차순으로''' 배치되어야 합니다. ㄹ자가 아니라 모든 행에서 왼쪽이 오른쪽보다 낮은 숫자여야 해요!
2. 카드끼리 연속적으로 붙여 놓을 때는 '''두 카드 숫자의 차이에 해당하는 카드만큼 버려야''' 합니다. 예를 들어, '3' 옆에 '5'를 두려면 2차이가 나니 두 개의 카드를 버려야 합니다.
두 장의 카드 사이에 놓을 때는, 더 작은 차이가 나는 결과값만큼 버리면 됩니다. 예를 들어, 10과 16 사이에 14를 둔다면, 14-10=4/ 16-14=2중 2가 더 낮으니 2장만 버리면 됩니다.
남은 카드 4장 이상을 버려야 하는 경우에는 카드를 내려놓을 수 없습니다.(즉, 4 이상 차이나는 숫자 카드끼리는 연속적으로 놓을 수 없습니다.)
==== 시작 카드 ====
시작 카드를 손에 들고 있는데 아직 맵에 시작 카드가 없는 상태라면, 자기 턴에 무조건 시작 카드를 내려놓아야 합니다.시작 카드는 격자 내에 배치되지 않고 왼쪽 하단 모서리에 배치됩니다.
시작 카드가 재생되면 플레이어들은 '''모두 합쳐 총 8장의 카드를 폐기'''해야 합니다.
여러분은 얼마나 많은 수의 카드를 폐기할 의향이 있는지 토론할 수 있지만, 여러분의 손에 무엇이 있는지, 나중에 어디에 숫자를 어떻게 내려놓을지에 대해서는 구체적으로 말하면 안 됩니다.
==== 종료 카드 ====
시작카드 포함 모든 격자가 채워진 후에만 종료 카드를 내려놓을 수 있습니다. 전원 다 할 수 있는 행동이 끝나지 않은 상태로 종료 카드를 내려놓으면, 여러분은 게임에서 승리하게 됩니다.
결승 카드는 일반 규칙에 따라 폐기될 수 있지만 게임에는 '''5개'''만 존재합니다! 다 채운다고 해도 종료 카드를 내려놓지 않으면 이길 수 없습니다.
=== ㄴ.두 장 버리기 ===
카드를 내려놓을 수 없거나 마음에 드는 패가 없다면 카드 두 장을 폐기할 수 있습니다.
== 4. 게임 종료 ===
격자를 모두 채운 후 플레이어가 성공적으로 Finish 카드를 내려놓으면 모두 승리합니다. 만약 한 명이라도 자기 차례에 할 수 있는 행동이 없다면 여러분은 모두 패배합니다.
'''1)숫자가 맞지 않거나, 2)플레이어가 카드를 버리기 위해 폐기할 카드가 충분하지 않거나, 3)차례를 시작할 때 카드를 하나 또는 0개만 가지고 있기 때문에 카드를 격자에 넣을 수 없다면 패배'''하는 것이죠.
== 5. 커뮤니케이션 지침 ==
엄밀히 말하면, 트랭퀼리티는 침묵 속에서 진행되어야 하는 게임입니다. 그러나 자신들만의 의사소통 규칙을 만들 수도 있겠죠.
== 6. 확장 규칙 ==
바다 몬스터 - 보드에 이미 놓인 카드를 제거할 수 있지만, 모든 플레이어가 바다 몬스터를 사용한 후에만 종료 카드를 내려놓을 수 있습니다!
1f44e250eef30d20f02b7a5bc26fd86c327166ca
1392
1391
2022-03-04T19:03:09Z
Producer Zenn
7863
wikitext
text/x-wiki
== 요약 ==
당신은 트랭퀼리티 호를 타고 낙원 섬을 찾으려고 합니다. 그를 위해 전체 6x6 바다 격자를 1-80번으로 표시된 섬 카드(시작 카드와 결승 카드 한 장)로 채워야 합니다. 격자를 완성하고 시작과 결승 카드를 놓아 섬의 낙원에서 하루를 보내게 된다면 모두 승리할 수 있습니다. 한 명의 플레이어가 더 이상 플레이를 할 수 없거나 카드를 더이상 버릴 수 없을 경우(섹션 4 참조) 영원히 길을 잃게 됩니다.
== 플레이 개요 ==
시작 카드에 대해 논의할 때를 제외하고는 '''다른 플레이어와 의사소통을 할 수 없습니다'''(아래 참조).
한 명씩 돌아가면서 첫 번째 플레이어부터 시작해서 시계방향으로 테이블을 돌게 됩니다. 자기 차례에는 다음 작업 중 하나를 수행하여 작업을 수행해야 합니다.
'''A) 카드를 격자에 내려놓거나'''
'''B) 카드를 두장 버리기'''
행동이 끝나면 자신의 개별 덱에서, 줄어든 만큼 카드를 보충해 5장을 채우고 다음 사람으로 넘어가게 됩니다.
== 상세 설명 ==
=== 카드 내려놓기 ===
카드를 손에서 선택하고 다음 규칙을 따른다면 그리드의 아무 곳에서나 재생할 수 있습니다.
1. 카드는 '''왼쪽 아래에서 오른쪽 위로 오름차순으로''' 배치되어야 합니다. ㄹ자가 아니라 모든 행에서 왼쪽이 오른쪽보다 낮은 숫자여야 해요!
2. 카드끼리 연속적으로 붙여 놓을 때는 '''두 카드 숫자의 차이에 해당하는 카드만큼 버려야''' 합니다. 예를 들어, '3' 옆에 '5'를 두려면 2차이가 나니 두 개의 카드를 버려야 합니다.
두 장의 카드 사이에 놓을 때는, 더 작은 차이가 나는 결과값만큼 버리면 됩니다. 예를 들어, 10과 16 사이에 14를 둔다면, 14-10=4/ 16-14=2중 2가 더 낮으니 2장만 버리면 됩니다.
남은 카드 4장 이상을 버려야 하는 경우에는 카드를 내려놓을 수 없습니다.(즉, 4 이상 차이나는 숫자 카드끼리는 연속적으로 놓을 수 없습니다.)
==== 시작 카드 ====
시작 카드를 손에 들고 있는데 아직 맵에 시작 카드가 없는 상태라면, 자기 턴에 무조건 시작 카드를 내려놓아야 합니다.시작 카드는 격자 내에 배치되지 않고 왼쪽 하단 모서리에 배치됩니다.
시작 카드가 재생되면 플레이어들은 '''모두 합쳐 총 8장의 카드를 폐기'''해야 합니다.
여러분은 얼마나 많은 수의 카드를 폐기할 의향이 있는지 토론할 수 있지만, 여러분의 손에 무엇이 있는지, 나중에 어디에 숫자를 어떻게 내려놓을지에 대해서는 구체적으로 말하면 안 됩니다.
==== 종료 카드 ====
시작카드 포함 모든 격자가 채워진 후에만 종료 카드를 내려놓을 수 있습니다. 전원 다 할 수 있는 행동이 끝나지 않은 상태로 종료 카드를 내려놓으면, 여러분은 게임에서 승리하게 됩니다.
결승 카드는 일반 규칙에 따라 폐기될 수 있지만 게임에는 '''5개'''만 존재합니다! 다 채운다고 해도 종료 카드를 내려놓지 않으면 이길 수 없습니다.
=== 두 장 버리기 ===
카드를 내려놓을 수 없거나 마음에 드는 패가 없다면 카드 두 장을 폐기할 수 있습니다.
== 게임 종료 ===
격자를 모두 채운 후 플레이어가 성공적으로 Finish 카드를 내려놓으면 모두 승리합니다. 만약 한 명이라도 자기 차례에 할 수 있는 행동이 없다면 여러분은 모두 패배합니다.
'''1)숫자가 맞지 않거나, 2)플레이어가 카드를 버리기 위해 폐기할 카드가 충분하지 않거나, 3)차례를 시작할 때 카드를 하나 또는 0개만 가지고 있기 때문에 카드를 격자에 넣을 수 없다면 패배'''하는 것이죠.
== 커뮤니케이션 지침 ==
엄밀히 말하면, 트랭퀼리티는 침묵 속에서 진행되어야 하는 게임입니다. 그러나 자신들만의 의사소통 규칙을 만들 수도 있겠죠.
== 확장 규칙 ==
바다 몬스터 - 보드에 이미 놓인 카드를 제거할 수 있지만, 모든 플레이어가 바다 몬스터를 사용한 후에만 종료 카드를 내려놓을 수 있습니다!
7461f00eb6454ad78a3b6074b5a732e40b74d2b7
Gamehelpcardiceo
0
187
1396
1248
2022-03-08T14:28:57Z
Kor yong
7827
wikitext
text/x-wiki
숫자 카드 총 60장
(1~15 각 4장씩)
주사위 3개
(4면체, 8면체, 12면체)
각자 숫자 카드 10장씩 받는다.
카드를 모두 제거하는 사람이 이긴다.
1. 선 플레이어는 주사위 3개를 굴린다.
2. 카드는 주사위 1~3개를 더한 값과 정확하게 일치하면 제거할 수 있다. 각 주사위는 한 번만 사용된다.
3. 더 이상 제거할 카드가 없으면 차례를 넘긴다.
4. 이전 사람이 사용한 주사위는 새로 굴리고, 사용하지 않은 주사위는 값이 유지된다. 동일한 방법으로 카드를 제거한다.
5. 만약 이전 사람이 주사위를 하나도 사용하지 않았다면, 주사위 값을 그대로 쓸지 아니면 새로 굴릴지 선택할 수 있다.
예)
선 플레이어는 주사위를 굴려 3, 4, 6이 나왔다. 3으로 카드 3을 제거하고 4,6을 더해서 카드 10을 제거한다. 차례를 넘긴다.
두 번째 플레이어는 모두 굴려서 4, 8, 12가 나왔다. 12를 사용해서 카드 12를 제거하고 차례를 넘긴다. 주사위 4, 8은 유지된다.
세 번째 플레이어는 12짜리 하나만 새로 굴려서 10이 나왔다. 4, 8, 10 중에 사용할 수 있는 것이 없어서 차례를 넘긴다.
네 번째 플레이어는 주사위를 새로 굴리는 것을 선택해서 3, 5, 7이 나왔다.
모두 사용해서 카드 3, 카드 5, 카드 7을 제거한다.
1ccc344a3f278a487f11a5fc9e2012dcf8a86b9d
1397
1396
2022-03-08T14:30:39Z
Kor yong
7827
wikitext
text/x-wiki
숫자 카드 총 60장
(1~15 각 4장씩)
주사위 3개
(4면체, 8면체, 12면체)
각자 숫자 카드 10장씩 받는다.
카드를 모두 제거하는 사람이 이긴다.
1. 선 플레이어는 주사위 3개를 굴린다.
2. 카드는 주사위 1~3개를 더한 값과 정확하게 일치하면 제거할 수 있다. 각 주사위는 한 번만 사용된다.
3. 더 이상 제거할 카드가 없으면 차례를 넘긴다.
4. 이전 사람이 사용한 주사위는 새로 굴리고, 사용하지 않은 주사위는 값이 유지된다. 동일한 방법으로 카드를 제거한다.
5. 만약 이전 사람이 주사위를 하나도 사용하지 않았다면, 주사위 값을 그대로 쓸지 아니면 새로 굴릴지 선택할 수 있다.
예)
선 플레이어는 주사위를 굴려 3, 4, 6이 나왔다. 3으로 카드 3을 제거하고 4,6을 더해서 카드 10을 제거한다. 차례를 넘긴다.
두 번째 플레이어는 모두 굴려서 4, 8, 12가 나왔다. 12를 사용해서 카드 12를 제거하고 차례를 넘긴다. 주사위 4, 8은 유지된다.
세 번째 플레이어는 12짜리 하나만 새로 굴려서 10이 나왔다. 4, 8, 10 중에 사용할 수 있는 것이 없어서 차례를 넘긴다.
네 번째 플레이어는 주사위를 새로 굴리는 것을 선택해서 3, 5, 7이 나왔다.
모두 사용해서 카드 3, 카드 5, 카드 7을 제거한다.
752a6cd19c04ff1f644b13fe81489e68451adb0e
Tips livingforest
0
228
1398
2022-03-12T15:47:18Z
Kor yong
7827
새 문서: 불테크가 제일 빠르다. 초반에 물방울 위주로 카드와 나무를 모은다. 전 사람이 선일 때(다음 라운드 나의 선일 때) 2불짜리 카드를 많이...
wikitext
text/x-wiki
불테크가 제일 빠르다.
초반에 물방울 위주로 카드와 나무를 모은다.
전 사람이 선일 때(다음 라운드 나의 선일 때) 2불짜리 카드를 많이 산다.
내가 선일 때 불을 많이 끈다(3~4개).
상대방 불토큰 뺏는다.
a69109ff4abe27373c336d4ff66e197d353c16e0
1399
1398
2022-03-12T15:53:06Z
Kor yong
7827
wikitext
text/x-wiki
초보는 불테크가 제일 빠르다.
초반에 물방울 위주로 카드와 나무를 모은다.
개인보드 오른쪽 하단에 나무를 심어 불끄기 추가 액션을 노린다(불토큰 많을 때).
전 사람이 선일 때(다음 라운드 나의 선일 때) 2불짜리 카드를 많이 산다.
내가 선일 때 불을 많이 끈다(2~3개).
상대방 불토큰을 뺏어 12개를 모은다.
7ee6145a5415e71fb1f65f1fe159343d56eecb73
1400
1399
2022-03-14T11:56:21Z
Kor yong
7827
wikitext
text/x-wiki
<불테크>
물 문양 위주로 카드와 나무를 모은다.
개인보드 오른쪽 하단에 나무를 심어 불끄기 추가 액션을 노린다(불토큰 많을 때).
전 사람이 선일 때(다음 라운드 나의 선일 때) 2불짜리 카드를 많이 산다.
내가 선일 때 최대한 불을 많이 끈다.
상대방 불토큰을 뺏어 12개를 모은다.
평가 : 한 라운드에 많으면 불 토큰 3~4개를 한 번에 모을 수 있다. 견제가 심해서 후턴이면 불을 못 끄는 경우가 있다.
<나무테크>
식물, 회오리 문양 위주로 모은다.
매 라운드 나무 행동을 꾸준히 한다.
가장자리에 4군데에 나무를 심어 보너스 행동을 한다.
원형 트랙에 나무 행동이 2군데 있는데 이걸 노려서 한 라운드에 나무 2개씩 심고 덤으로 나무 토큰도 뺏는다.
평가 : 안정적이고 혼자 앞서나가면 막을 수 없다. 물 문양이 적을 때 불카드 받을 위험이 크다.
4185608d0c055d89c8ffebfd4c9c9026a383f887
Gamehelpschroedingerscats
0
220
1402
1401
2022-03-16T08:25:05Z
Kor yong
7827
/* 박스 카드 종류 */
wikitext
text/x-wiki
== 세팅 ==
a) 각 플레이어마다 한 장의 박사 카드가 지급되고 폐기 더미 안에 한 장의 박사 카드를 둡니다.
b) 각 플레이어에게 플레이어 수와 동일한 상자 수를 나누어 줍니다. (예: 플레이어 4명일 시 상자카드 4장)
c) 연구 덱을 세팅한다.
== 박스 카드 종류 ==
'''살아있는 고양이 카드'''
가장 낮은 랭크의 카드입니다. 총 20장이 덱에 들어있습니다.
'''죽은 고양이 카드'''
살아있는 고양이보다는 랭크가 높지만 빈 상자보다는 순위가 낮습니다.총 20장이 덱에 들어있습니다.
'''빈 박스'''
가장 높은 랭크의 카드입니다. 가설을 제시할 때 두 배의 가치를 지닙니다. 총 8장이 덱에 들어있습니다.
(예) 가치 : 살아있는 2장<죽은 2장<빈 1장
'''하이젠베르크'''
이것은 와일드 카드(조커)입니다. 이것은 항상 직전에 제시되었던 가설과 동일한 카드로 간주됩니다. 따라서 하이젠베르크를 가지고 가설을 세우는 것은 불가능합니다. 총 4장이 덱에 들어있습니다.
== 내 턴에 할 일 ==
a-1) 가설 배팅 패널에서 배팅을 합니다. 배팅이란, '''나를 포함한 전원이 손에 들고 있는 패 중에 과연 '살아있는/죽은/빈' 카드가 모두 몇 장인지를 찍는 것'''입니다.
배팅을 할 때는 '''항상 직전에 제시된 가설보다 더 높은 랭크-즉, 오른쪽 또는 하단-으로만 상위입찰'''을 할 수 있습니다.
b) 그런 다음 현재 입찰과 일치하는 유형의 카드를 내려놓아 결과를 보여줄 수 있습니다.(보여주지 않아도 됩니다) ex)살아있는 고양이가 5마리 있다고 배팅했다면, 손에 든 카드 중 살아있는 고양이 카드를 한 장 공개할 수 있다.
그런 다음 공개한 카드 장수 만큼 손에 남은 카드를 버리고 버린 장수만큼 다시 가져올 수 있습니다.
c) 박사학위(고양이 물리학자 카드)를 공개할 수 있습니다. 이 경우 한번 사용하면 게임이 끝날 때까지 더이상의 박사학위 카드는 사용이 불가능합니다.
a-2) 만약 당신이 직전에 배팅한 사람의 가설이 거짓이라고 생각한다면 의문을 제기합니다.
그러면 모두가 손에 든 카드가 공개되고, 모두가 가진 고양이 카드의 개수가 합산되어 가설이 맞는지 아닌지 세어볼 수 있습니다.
앞사람의 가설이 틀렸다면 그 사람이 게임에서 아웃되고, 가설이 맞았다면 의문을 제기한 사람이 아웃됩니다.
== 박사 학위 능력 ==
이름-능력 순
Albert Felinestein 당신의 연구를 버리고 버린 만큼 다시 뽑을 수 있습니다.
Cecelia Pounce 이 연구에 살아있는 고양이 숫자 2마리를 더합니다.
Madam Purrie 공개되어 있는 살아있는 고양이 카드를 모두 버립니다.
Maria Goeppertmeower 이 연구에 빈 박스를 하나 더합니다.
Mittens Faraday 공개되어 있는 죽은 고양이 카드를 모두 버립니다.
Neil Degrasse Tabby 공개된 물리학자 카드의 효과를 복사합니다.
Sally Prride 이번 턴에 버려진 카드 더미를 확인할 수 있습니다.
Sir Isaac Mewton 연구 덱에서 추가로 2장의 카드를 뽑습니다.
Stephen Pawking 당신의 가설 세우기 단계를 패스합니다.
Whiskers Feyncat 이 연구에 하이젠베르크 카드 개수를 제외합니다.
bf7a6b98c65453a620238c52c6ca5c9ff785ec34
Gamehelppyrgos
0
211
1403
1357
2022-03-20T19:06:07Z
Ufm
6353
wikitext
text/x-wiki
== 구성품 ==
* 4x4 격자 게임판
* 2색의 말 15개씩 (사각형 말 5개, 삼각형 말 5개, 원통 말 5개)
== 게임 컨셉 ==
피르가는 간단한 2인 추상전략게임입니다.
플레이어는 탑을 짓는 건축가가 됩니다. 자기가 놓는 말로 다음에 상대가 어디에 말을 놓을지 결정합니다. 먼저 탑 3개를 차지하면 승리합니다.
== 준비 ==
각자 색깔을 결정하고 자기 앞에 자기 색깔의 말 15개를 둡니다.
== 게임 방식 ==
자기 차례에는 아래의 규칙에 따라 자기 말 하나를 골라 놓습니다.
1) 한 칸에는 색깔에 무관하게 삼각형, 사각형, 원통 하나씩을 배치할 수 있습니다. 말이 칸에 놓인 순서는 게임에 영향을 미치지 않습니다.
2) '''사각형'''을 놓으면 다음 플레이어는 수직이나 수평으로 인접한 칸에 말을 놓아야 합니다.
3) '''삼각형'''을 놓으면 다음 플레이어는 삼각형의 방향에 맞게 말을 놓아야 합니다. 삼각형을 놓은 플레이어가 방향을 결정하며, 이 방향은 나중에 바꿀 수 없습니다.
게임판의 테두리에서 삼각형이 게임판 바깥을 향하도록 놓을 수는 없습니다.
4) '''원통'''을 놓으면 다음 플레이어는 같은 칸에 말을 놓아야 합니다.
게임을 시작할 때는 하얀색 플레이어가 빈칸 하나에 말을 놓습니다. '''선공은 첫 수로 사각형을 2번 연속으로 놓을 수는 없습니다.'''
이미 말이 1개나 2개 있는 곳에도 배치 규칙을 지킨다면 같은 칸에 말을 놓을 수 있습니다.
위의 규칙에 따라 말을 놓을 수 없다면 게임판의 빈칸 하나를 골라 말을 놓아야 합니다.
빈칸에 둘 수도 없다면 게임이 즉시 끝납니다.
누군가가 한 칸에 3번째 말을 놓아 탑을 완성시키면 완성된 탑에 자기 말의 수가 더 많은 플레이어가 탑을 차지합니다.
== 게임 종료 ==
완성된 탑 3개를 차지하면 즉시 승리합니다.
아무도 탑을 차지하지 못했다면 차지한 완성된 탑의 수가 가장 많은 사람이 승리합니다.
차지한 완성된 탑의 수가 같으면 차지한 미완성인 탑 중 말이 2개 놓인 탑의 수를 먼저 비교하고, 여전히 동률이면 말이 1개 놓인 탑의 수를 비교합니다. 이번에도 동률이면 무승부입니다.
b1a32641e62405680f10d31f86684b967eaa5764
Tips wizard
0
229
1404
2022-04-04T07:18:36Z
JongEokLee
8029
상대방의 비장의 카드를 "낚시" 하세요
wikitext
text/x-wiki
손놀림
광대와 마법사
이것들이 당신의 손에 있다면 일반적으로 트릭의 결과를 보장할 수 있습니다. 데크에 각각 4개씩 있습니다. 마법사는 먼저 플레이하면 승리를 보장합니다. 광대는 일반적으로 플레이어가 첫 번째 플레이어가 아닌 한 패배를 보장합니다. 턴 수, 손에 있는 광대 수 대 덱 및 상대를 기준으로 측정하고 상대방이 필요로 하는 것을 측정합니다(더 많은 트릭이 필요합니까?)
손에 수트 제한
나중 턴에서 유연성을 허용하기 위해 정장을 벗으십시오.
예를 들어 슈트가 없으면 트럼프 카드를 사용할 수 있습니다. 슈트가 없으면 다른 슈트 카드를 제거할 수 있습니다.
트럼프와 라운드 시작
낮은 비장의 카드를 가지고 있고 턴에서 먼저 가려면 그것을 사용하여 다른 플레이어의 비장의 카드를 "낚시"하십시오
076894895e05f62dca79663999d6ae7e445d8498
Gamehelptrusis
0
230
1405
2022-05-26T11:19:51Z
Producer Zenn
7863
새 문서: == 게임의 목표 == * ''인간 팀'' : 모든 트루시스를 죽이세요. * ''트루시스 팀'' : 트루시스 팀의 구성원수가 다른 캐릭터들 숫자보다 많아지...
wikitext
text/x-wiki
== 게임의 목표 ==
* ''인간 팀'' : 모든 트루시스를 죽이세요.
* ''트루시스 팀'' : 트루시스 팀의 구성원수가 다른 캐릭터들 숫자보다 많아지거나, 다른 팀의 플레이어를 모두 죽여야 합니다.
* ''캐스트어웨이 팀'' : 다른 팀의 승리조건이 갖추어졌을 때 캐스트어웨이 팀원 중 한 명이라도 살아있다면 인간/트루시스 팀의 승리를 무시하고 캐스트어웨이팀의 승리로 간주합니다.
== 게임 플레이 ==
플레이어는 게임 도중 언제든지 공개 또는 비공개적으로 말할 수 있습니다.
게임의 성공을 위해 모두가 적극적으로 토론에 참여해 의심하고 고발하고 방어하는 것이 바람직합니다.
경기 중 사망한 플레이어들은 여전히 말은 할 수 있지만, 더이상 특수능력을 사용하지는 못합니다.
=== 낮☀️ ===
게임은 DAY 단계부터 시작됩니다. 매일 살아있는 모든 플레이어는 토론을 거쳐 죽일 다른 플레이어를 투표할 수 있습니다.
투표는 선택 사항이며, 플레이어들은 패스할 때까지 투표 내용을 변경할 수 있습니다.
단계가 끝나면 가장 많은 표를 얻은 플레이어가 사망합니다. 동점일 경우, 아무도 죽지 않습니다.
낮 동안, 낮 특수능력을 가진 캐릭터들은 그것들을 사용할 수 있습니다.
=== Night 🌙 ===
매일 밤, 살아있는 트루시스들은 죽일 플레이어를 투표할 수 있습니다.
투표는 선택 사항이며, 트루시스 플레이어들은 패스할 때까지 투표 내용을 변경할 수 있습니다.
단계가 끝나면 가장 많은 표를 얻은 플레이어가 사망합니다. 동점일 경우, 아무도 죽지 않을 것이다.
밤 동안, 밤 특수능력을 가진 캐릭터들은 그것들을 사용할 수 있습니다.
== 캐릭터 ==
=== 인간 팀 ===
* ''인간'' : 특수능력이 없는 평범한 인간입니다.
* ''청소부'' : 매일 밤 청소부는 살아있는 플레이어를 한 명 선택하여 플레이어가 트루시스인지, 캐스트웨이인지, 둘 중 어느 쪽도 아닌지를 확인합니다.
* ''묘지기'' : 밤마다 묘지기는 낮동안 죽은 사람이 트루시스였는지 아닌지를 알 수 있습니다. 본인이 이미 죽은 다음 발생한 사망에 대해서는 알 수 없습니다.
* ''사제'' : 밤마다 트루시스가 죽일 것으로 예상되는 플레이어를 1명 보호할 수 있습니다.
* ''여현자'' : 밤마다 여현자는 한 명을 선택해, 다음날 있을 투표에서 보이지 않는 표를 추가로 행사합니다.
* ''백기사'' : 낮이든 밤이든 백기사는 죽은 선수를 다음 단계에서 되살리기 위해 자신을 희생할 수 있습니다.
=== 트루시스 팀 ===
* ''트루시스'' : 트루시스는 다른 모든 트루시스들의 정체를 알고 있습니다. 매일 밤 죽일 플레이어에게 투표할 수 있으며, 어떤 플레이어를 제거할지를 결정하기 위해 트루시스가 조정하는 것이 좋습니다.
* ''도살자'' : 날카로운 칼과 피에 대한 갈증을 가지고 있지만 특별한 힘은 없습니다.
* ''환상술사'' : 낮 동안 환상술사는 두 표를 행사할 수 있습니다. 하나는 가짜지만 외부에 공개되는 것이고, 하나는 진짜지만 남들에게 드러나지 않는 것으로, 죽일 플레이어 결정시에는 이 보이지 않는 가짜표가 가산됩니다.
* ''예언자'' : 밤마다 예언자는 살아있는 플레이어를 한 명 선택하여, 그 플레이어의 정확한 직업을 확인할 수 있습니다.
* ''흑기사'' : 낮이든 밤이든, 블랙나이트는 죽은 플레이어를 다음 단계에서 되살리기 위해 자신을 희생할 수 있습니다.
* ''자폭병'' : 밤 동안 자폭병은 플레이어를 죽이기 위해 자신을 희생할 수 있습니다. 자폭병의 표적이 된 플레이어는 사제의 보호를 받을 수 없습니다.
* ''도굴꾼'' : 도굴꾼은 다른 모든 도굴꾼(2명 이상일 경우)와 트루시스의 신원을 알고 있습니다. 도굴꾼은 매일 트루시스들에 의해 살해된 플레이어의 정확한 역할을 알게 됩니다.
=== 캐스트어웨이 팀 ===
* ''캐스트어웨이'' : 캐스트어웨이는 특별한 힘이 없고 다른 캐스트어웨이의 정체를 알지 못합니다.
== 게임 세팅 ===
* 표준 세팅 :게임 내 플레이어 수에 따라 미리 정해진 캐릭터가 할당된 게임입니다. 인원수에 맞게 한 직업씩 더해 나가세요!
** ''기본 5 캐릭터(필수)'': 인간, 인간, 트루시스, 청소부, 도살자
** ''다음 캐릭터(6인~30인)'' : 사제(6인), 인간(7인), 트루시스(8인), 묘지기(9인), 환상술사(10인), 여현자(11인), 예언자(12인), 백기사(13인), 흑기사(14인), 캐스트어웨이(15인), 자폭병(16인), 청소부(17인), 도굴꾼(18인), 사제(19인), 트루시스(20인), 묘지기(21인), 예언자(22인), 캐스트어웨이(23인), 여현자(24인), 자폭병(25인), 백기사(26인), 흑기사(27인), 인간(28인), 인간(29인), 캐스트어웨이(30인)
* 커스텀 세팅
플레이어는 참여하는 플레이어의 수에 따라 게임에 포함할 캐릭터를 자유롭게 선택할 수 있습니다. 하나 이상의 팀에 대한 과도한 유리함을 피하면서 균형 잡힌 세트를 선택하는 것이 좋습니다.
캐릭터 선택을 위한 몇 가지 지침: 게임은 최소 8명의 플레이어와 함께 플레이하는 것이 이상적입니다. 더 적은 수의 플레이어가 있는 게임은 허용되지만 플레이 가능성이 낮을 수 있습니다.
다른 캐릭터와 상관없이 7인 이상은 트루시스 2명, 11인 이상은 트루시스 3명 등이어야 합니다.
트루시스와 캐스트어웨이 팀의 캐릭터 수를 합친 것보다 인간 팀의 캐릭터가 더 많아야 합니다.
0042fb5c4bba5f156d2c6ce9a2fd2349fd53903c
Gamehelptheninedomains
0
231
1406
2022-07-15T05:41:55Z
Fruitbat351
8200
새 문서: 목표 : 4종류의 원소(색상)를 모두 모으거나 게임 종료시 상대방보다 점수가 더 높으면 승리합니다. 게임 방법 : 게임은 3라운드로 진행...
wikitext
text/x-wiki
목표 :
4종류의 원소(색상)를 모두 모으거나 게임 종료시 상대방보다 점수가 더 높으면 승리합니다.
게임 방법 :
게임은 3라운드로 진행되며, 각 라운드마다 세 개의 카드더미에서 도메인 카드가 각각 한 장씩 공개됩니다. 플레이어들은 세 장의 도메인 카드 앞에 보유한 숫자카드를 한 장씩 제출하며, 모든 카드가 배치되면 카드를 공개합니다. 더 높은 카드를 제출한 플레이어가 승리하며, 해당 대결의 도메인 카드를 가져옵니다. 획득한 도메인 카드는 플레이어 앞에 정면으로 배치되며, 사용된 카드는 앞면이 보이도록 버려집니다. 한 플레이어가 도메인 카드에 그려진 4종류의 원소(색상)를 모두 모으면 게임이 즉시 종료되며, 그렇지 않은 경우 다음 라운드를 시작합니다. (3라운드까지 진행될 경우 도합 9번의 대결이 이루어집니다.)
세 라운드가 종료될 동안 어느 플레이어도 모든 종류의 원소를 모으지 못했다면, 더 많은 점수를 획득한 플레이어가 승리합니다.
게임 구성 :
도메인 카드: 게임에는 2 ~ 10이 적힌 총 9장의 도메인 카드가 사용되며, 각 카드에 적힌 숫자는 해당 도메인 카드의 승점이 됩니다.
2 ~ 7까지의 도메인 카드는 승점과 함께 원소를 획득할 수 있으며, 8 ~ 10 도메인 카드는 높은 승점을 가진 대신 원소는 가지고 있지 않습니다.
원소 :도메인 카드에는 4종류의 원소(빨강,초록,파랑,보라)가 표시되어 있으며, 한 플레이어가 네 종류의 원소를 모두 모았다면 즉시 해당 플레이어의 승리로 게임을 종료합니다.
보라색 원소 절반이 그려진 도메인카드의 경우 두 장을 모아야 보라색 원소 한 개로 취급합니다.
(두 플레이어가 같은 턴에 4종류의 원소를 모두 획득하는 경우, 게임은 종료되지 않으며 획득한 점수로 승패를 가립니다,)
카드와 대결 : 기본 카드의 숫자 범위는 0 ~ 5입니다. (0, 1, 2, 3, 4, 5)
두 카드가 대결할 때는 기본적으로 높은 숫자가 승리합니다. 예외적으로, 0카드는 5카드를 상대로 승리합니다.
카드가 전투의 결과를 바꾸는 특수 효과를 가지고 있다면((0, -4, * 등) 대결 값과 보너스는 무시되고 효과만 계산됩니다.
같은 크기의 카드끼리 대결하는 경우:
- 받는 대결 보너스가 더 높은 카드가 동률에서 승리합니다. (대결 보너스는 일부 특수카드들의 효과로 적용됩니다)
(전 라운드 1+카드의 효과로 +2의 대결 보너스를 받은 2카드는 기본 카드 4카드를 상대로 승리합니다.)
대결 보너스가 없는 경우 (또는 보너스의 크기가 같을 경우) :
- 정확히 같은 카드인 경우: 누구도 대결에서 승리하지 못하며. 해당 대결의 도메인 카드는 게임에서 제거됩니다.
- 그 외의 경우: 특수카드의 기호표기에 따라 승패를 결정합니다. +카드는 기본카드를 상대로 승리하며, -카드는 기본카드를 상대로 패배합니다.
(3+카드는 3카드에게 승리하며, 3-카드는 3카드에게 패배합니다.)
특수카드:
특수카드 능력은 해당 카드에 커서를 가져다 대면 확인할 수 있습니다. (설정에서 툴팁 표시를 활성화하세요!)
특수카드 능력 :
1-: 인접한 카드의 크기를 +1(또는 한 카드만 인접할 경우 +2) 증가시킵니다.
1+: 이 카드가 있는 칸에 들어오는 다음 카드의 크기를 +2 증가시킵니다.
2-: 이 카드로 대결에서 승리한다면, 소유자는 자신이 보유한 도메인 카드 한 장과 상대가 보유한 도메인 카드 한 장을 교환합니다. (이 효과는 원소 승리 판별 이전에 적용합니다)
2+: 이 카드가 있는 칸에 들어오는 다음 카드의 크기를 +1 증가시킵니다.
3-: 이 카드로 대결에서 승리한다면, 소유자는 자신의 카드 중 하나를 자신이 이미 사용한 카드 중 하나와 교환할 수 있습니다.
3+: 이 카드가 2 이상의 차이로 대결에서 승리할 경우 제출자는 승점 7점을 획득합니다.
4-: 이 카드는 기본 카드 "1" 및 카드 "*"과의 대결에서 패배합니다.
4+: 이 카드가 있는 칸에 들어오는 다음 카드의 크기를 -1 감소시킵니다. (이번이 세 번째 라운드라면 이 카드의 크기를 -2 감소시킵니다.)
*: 이 카드는 기본 카드 "3", "4", "5" 와 특수카드 4-를 상대로 승리하며, 다른 카드와의 대결에서 모두 패배합니다. (대결 보너스 등은 고려하지 않습니다.)
74643aaec54c2b8888391c5f9f9e5b11129a049c
1407
1406
2022-07-15T05:43:13Z
Fruitbat351
8200
wikitext
text/x-wiki
목표 :
4종류의 원소(색상)를 모두 모으거나 게임 종료시 상대방보다 점수가 더 높으면 승리합니다.
게임 방법 :
게임은 3라운드로 진행되며, 각 라운드마다 세 개의 카드더미에서 도메인 카드가 각각 한 장씩 공개됩니다. 플레이어들은 세 장의 도메인 카드 앞에 보유한 숫자카드를 한 장씩 제출하며, 모든 카드가 배치되면 카드를 공개합니다. 더 높은 카드를 제출한 플레이어가 승리하며, 해당 대결의 도메인 카드를 가져옵니다. 획득한 도메인 카드는 플레이어 앞에 정면으로 배치되며, 사용된 카드는 앞면이 보이도록 버려집니다. 한 플레이어가 도메인 카드에 그려진 4종류의 원소(색상)를 모두 모으면 게임이 즉시 종료되며, 그렇지 않은 경우 다음 라운드를 시작합니다. (3라운드까지 진행될 경우 도합 9번의 대결이 이루어집니다.)
세 라운드가 종료될 동안 어느 플레이어도 모든 종류의 원소를 모으지 못했다면, 더 많은 점수를 획득한 플레이어가 승리합니다.
게임 구성 :
도메인 카드: 게임에는 2 ~ 10이 적힌 총 9장의 도메인 카드가 사용되며, 각 카드에 적힌 숫자는 해당 도메인 카드의 승점이 됩니다.
2 ~ 7까지의 도메인 카드는 승점과 함께 원소를 획득할 수 있으며, 8 ~ 10 도메인 카드는 높은 승점을 가진 대신 원소는 가지고 있지 않습니다.
원소 :도메인 카드에는 4종류의 원소(빨강,초록,파랑,보라)가 표시되어 있으며, 한 플레이어가 네 종류의 원소를 모두 모았다면 즉시 해당 플레이어의 승리로 게임을 종료합니다.
보라색 원소 절반이 그려진 도메인카드의 경우 두 장을 모아야 보라색 원소 한 개로 취급합니다.
(두 플레이어가 같은 턴에 4종류의 원소를 모두 획득하는 경우, 게임은 종료되지 않으며 획득한 점수로 승패를 가립니다,)
카드와 대결 : 기본 카드의 숫자 범위는 0 ~ 5입니다. (0, 1, 2, 3, 4, 5)
두 카드가 대결할 때는 기본적으로 높은 숫자가 승리합니다. 예외적으로, 0카드는 5카드를 상대로 승리합니다.
카드가 전투의 결과를 바꾸는 특수 효과를 가지고 있다면((0, -4, * 등) 대결 값과 보너스는 무시되고 효과만 계산됩니다.
같은 크기의 카드끼리 대결하는 경우:
- 받는 대결 보너스가 더 높은 카드가 동률에서 승리합니다. (대결 보너스는 일부 특수카드들의 효과로 적용됩니다)
(전 라운드 1+카드의 효과로 +2의 대결 보너스를 받은 2카드는 기본 카드 4카드를 상대로 승리합니다.)
대결 보너스가 없는 경우 (또는 보너스의 크기가 같을 경우) :
- 정확히 같은 카드인 경우: 누구도 대결에서 승리하지 못하며. 해당 대결의 도메인 카드는 게임에서 제거됩니다.
- 그 외의 경우: 특수카드의 기호표기에 따라 승패를 결정합니다. +카드는 기본카드를 상대로 승리하며, -카드는 기본카드를 상대로 패배합니다.
(3+카드는 3카드에게 승리하며, 3-카드는 3카드에게 패배합니다.)
특수카드:
특수카드 능력은 해당 카드에 커서를 가져다 대면 확인할 수 있습니다. (설정에서 툴팁 표시를 활성화하세요!)
특수카드 능력 :
1-: 인접한 카드의 크기를 +1(또는 한 카드만 인접할 경우 +2) 증가시킵니다.
1+: 이 카드가 있는 칸에 들어오는 다음 카드의 크기를 +2 증가시킵니다.
2-: 이 카드로 대결에서 승리한다면, 소유자는 자신이 보유한 도메인 카드 한 장과 상대가 보유한 도메인 카드 한 장을 교환합니다. (이 효과는 원소 승리 판별 이전에 적용합니다)
2+: 이 카드가 있는 칸에 들어오는 다음 카드의 크기를 +1 증가시킵니다.
3-: 이 카드로 대결에서 승리한다면, 소유자는 자신의 카드 중 하나를 자신이 이미 사용한 카드 중 하나와 교환할 수 있습니다.
3+: 이 카드가 2 이상의 차이로 대결에서 승리할 경우 제출자는 승점 7점을 획득합니다.
4-: 이 카드는 기본 카드 "1" 및 카드 "*"과의 대결에서 패배합니다.
4+: 이 카드가 있는 칸에 들어오는 다음 카드의 크기를 -1 감소시킵니다. (이번이 세 번째 라운드라면 대신 이 카드의 크기를 -2 감소시킵니다.)
*: 이 카드는 기본 카드 "3", "4", "5" 와 특수카드 4-를 상대로 승리하며, 다른 카드와의 대결에서 모두 패배합니다. (대결 보너스 등은 고려하지 않습니다.)
182fa3f8779d7cfa5159f9747298d3e6d2233bbb
Gamehelpstrands
0
232
1408
2022-07-15T06:15:41Z
Fruitbat351
8200
새 문서: 게임 준비 게임판의 크기와 모양을 설정합니다. 한 플레이어는 백을, 다른 플레이어는 흑을 잡고 시작합니다. 게임 진행 흑이 2로 표...
wikitext
text/x-wiki
게임 준비
게임판의 크기와 모양을 설정합니다.
한 플레이어는 백을, 다른 플레이어는 흑을 잡고 시작합니다.
게임 진행
흑이 2로 표시된 칸 중 하나를 덮는 것으로 시작합니다.
다음은 백이 턴을 가지며, 그다음부터는 숫자 칸을 교대로 덮으면서 진행합니다.
자신의 턴에는 숫자 하나를 고른 뒤, 그 숫자만큼의 해당 숫자 칸을 자신의 색 돌로 덮습니다.
예를 들어, 3을 고른 후 아무 3이 적힌 칸 세 개를 골라 자신의 말로 해당 숫자를 덮을 수 있습니다. (돌이 꼭 연결될 필요는 없습니다)
고른 숫자의 덮을 칸이 부족한 경우, 남아있는 칸을 모두 덮습니다. (추가 기회를 획득하지는 않습니다)
게임 종료
게임판이 모두 덮였을 때 종료됩니다.
자신의 말이 이어진 그룹이 더 큰 플레이어가 게임에서 승리합니다. 가장 큰 그룹의 크기가 서로 같다면 다음으로 큰 그룹의 크기를 순서대로 계속해서 비교합니다. 이 게임에 무승부는 없습니다!
3edd54da140314dac616e8fe7972b00ab25cd857
1409
1408
2022-07-15T06:19:24Z
Fruitbat351
8200
wikitext
text/x-wiki
게임 준비
게임판의 크기와 모양을 설정합니다.
한 플레이어는 백을, 다른 플레이어는 흑을 잡고 시작합니다.
게임 진행
흑이 2로 표시된 칸 중 하나를 덮는 것으로 시작합니다.
다음은 백이 턴을 가지며, 그다음부터는 숫자 칸을 교대로 덮으면서 진행합니다.
자신의 턴에는 숫자 하나를 선택한 뒤, 그 숫자만큼의 해당 숫자 칸을 자신의 색 돌로 덮습니다.
예를 들어, 3을 고른 후 아무 3이 적힌 칸 세 개를 골라 자신의 돌로 해당 숫자를 덮을 수 있습니다. (돌이 꼭 연결될 필요는 없습니다)
고른 숫자의 덮을 칸이 부족한 경우, 남아있는 칸을 모두 덮습니다. (추가 기회를 획득하지는 않습니다)
게임 종료
게임판이 모두 덮였을 때 종료됩니다.
자신의 말이 이어진 그룹이 더 큰 플레이어가 게임에서 승리합니다. 가장 큰 그룹의 크기가 서로 같다면 다음으로 큰 그룹의 크기를 순서대로 계속해서 비교합니다. 이 게임에 무승부는 없습니다!
a1dab7bacd5a883d835987a675715bebe51f4c87
Gamehelpcatan
0
233
1410
2022-07-25T18:32:28Z
Seungseop22
8247
새 문서: 게임 목표 (다양한 건물과 개발 카드를 구매할 수 있도록 자원 카드를 최대한 얻으세요! 그러면 10점에 도달하는 첫번째 플레이어가 될 수...
wikitext
text/x-wiki
게임 목표
(다양한 건물과 개발 카드를 구매할 수 있도록 자원 카드를
최대한 얻으세요! 그러면 10점에 도달하는 첫번째 플레이어가
될 수 있습니다!)
게임 준비
(게임판에 랜덤으로 장소에 언덕(벽돌), 숲(목재), 산(광석), 들판(곡물), 목초지, 사막(얻을수 있는 자원 x)
으로 구성되어 있습니다.
사막을 제외한 각 지형에는 2~12개의 숫자가 있습니다
사막에는 도둑을 넣고 시작합니다 . 그 후
각 플레이어는 차례대로 원하는 자리에 마을을 넣고 도로를
건설합니다 차례대로 건설했으면 다시 역순으로 건설합니다.)
게임 시작
(자원 생산을위한 주사위 던지기 (필수) :
당신의 차례에서 두 주사위를 던져 합계를 계산합니다.
주사위 결과값이 나온 지형의 근처에 자신의 마을이 있으면
그 지형의 자원을 가져옵니다(단, 강도나 도둑이 있을경우 가져올 수 없습니다)
7이 나오면 아무도 자원을 얻지 않고 8 개 이상의 자원을 가진 플레이어는 절반을 버려야합니다. 강도(도둑)를 새로운 지형으로 이동하고 지형 옆에 마을이나 도시가 있는 플레이어로부터 임의의 자원을 하나 무조건 훔쳐야 합니다.
거래(선택사항): 자신의 차례동안 다른 플레이어들이랑 거래가 가능합니다.
또한 모든 플레이어는 같은 자원 카드 4장을 원하는 자원 1장과 교환할 수 있으며, 해상무역을 할라면 거기까지 도로를 건설한뒤 거기에 말하는 거래값으로 교환이 가능합니다.
건설카드와 마을구입(선택사항): 얻은 자원카드들로
구입 비용이 충족반 된다면 개발카드와 마을과 도로를 구입 할
수 있습니다
도로는 첫 번째 마을에 반드시 연결해야하며 도로는 벽돌1개,목재1개 가격이 듭니다
마을을 지을때도 기존마을과 연결하여 지어야하며 마을은
벽돌 1개 목재 1개 양1마리 곡물 1개 비용이 듭니다
마을은 도시로도 업그레이드가 가능하며 업그레이드 비용은
3개의 돌, 2개의 곡물로 가능합니다.
개발카드는 돌 1개 양 1개 곡물 1개로 구입가능하며
기사카드(도둑옮기기) , 자원창고(원하는 자원 2개가져오기)
, 도로건설등 다양하게 있으며 , 개발카드를 잘 사용할경우
특수 점수를 독점 흭득 가능합니다.
개발카드는 얻은 다음 바로 사용불가하며, 다음턴 주사위
굴리기전에 사용가능합니다.
득점 : 마을은 1점 , 도시는 2점 ,개발카드엔 1점의 승리카드가 있으며 (게임종료조건을 달성하기전까진 비공개)
기사 카드 최소 3장으로 가장 많이 쓴 사람이 기사독점카드(2점) 흭득하며 도로도 최고로 많이 지은 사람이(최소 5도로) 2점을 얻습니다 (카드 갯수가 다른플레이어와 중복일경우
먼저 얻은 사람이 계속 업적카드를 유지합니다)
게임 종료
게임 동안 승리 포인트가 10 이상인 경우 (승점카드 포함)플레이어가 나올경우 게임이 종료되며 그 사람의 승리가 됩니다.
cb74d976533ff9124f362da23de853b3f99c3aa6
Gamehelpladyandthetiger
0
234
1411
2022-07-30T13:00:47Z
Samosal
8196
새 문서: ● 모든 카드는 2가지 '특성'을 가지고 있다. -색깔 : 빨강 또는 파랑 -역할 : 여자 또는 호랑이 (예 : 빨강호랑이, 빨강여자, 파랑여자)...
wikitext
text/x-wiki
● 모든 카드는 2가지 '특성'을 가지고 있다.
-색깔 : 빨강 또는 파랑
-역할 : 여자 또는 호랑이
(예 : 빨강호랑이, 빨강여자, 파랑여자)
● 구성물 :
-정체카드 4장(빨여, 빨호, 파여, 파호 각 1장씩)
-단서카드 12장(빨여, 빨호, 파여, 파호 각 3장씩)
-와일드카드 2장(여/호, 빨/파 각 1장씩)
(예 : 여/호 카드는 여자 or 호랑이로 사용할 수 있다.)
● '묶음'이란 자신의 정체와 특성 1가지가 같은 4장의 카드들을 말한다.
(예 : 나의 정체는 파랑호랑이인데 파랑카드 4장을 모으거나 호랑이카드 4장을 모으면 된다. 호랑이카드 4장 = 빨호, 파호, 빨호, 여/호)
● 게임 목표 : 10점 달성하면 승리
'수집가'는 자신의 정체와 같은 묶음(4장)을 모으거나 추측자가 자신의 정체를 추리하는 것을 실패하도록 유도한다.
'추측자'는 수집가의 정체를 맞추거나 수집가보다 먼저 묶음을 만들면 된다.
● 라운드 세팅 :
1명은 수집가, 다른 1명은 추측자를 맡고 정체카드를 랜덤으로 1장씩 받는다.
단서카드와 와일드카드를 섞어 덱을 만든 후 4장을 공개한다.
수집가부터 행동을 시작한다.
● 라운드 순서 :
1. 수집가는 공개된 단서카드 4장 중에서 1장을 가져오고, 즉시 덱에서 1장을 공개한다.
2. 수집가는 묶음을 만들거나 차례를 넘긴다.
1) 묶음을 만든다. 자신의 정체와 특성 1가지가 같은 4장의 카드들을 모았다면 6점을 받고 라운드 종료.
2) 차례를 넘긴다.
3. 추측자는 정체를 추리하거나 묶음을 만들거나 공개된 카드 1장을 버린다(초반에는 카드 버리기).
1) 수집가의 정체를 추리한다.
(안전하게) 역할 또는 색깔을 맞추면 1점을 받고 라운드 종료.
(확실하면) 역할 그리고 색깔을 맞추면 5점을 받고 라운드 종료.
(실패)하나라도 틀리면 수집가가 4점을 받고 라운드 종료.
2) 묶음을 만든다.
수집가가 모은 카드 중에서 자신의 정체와 같은 묶음이 있다면 2점을 받고 라운드 종료.
3) 추측자는 공개된 단서카드 4장 중에서 1장을 버리고, 즉시 덱에서 1장을 공개한다. 이때 덱이 다 떨어지면 3점을 받고 라운드 종료.
4. 추측자는 정체를 추리하거나 묶음을 만들거나 차례를 넘긴다.
1) 수집가의 정체를 추리한다.
2) 묶음을 만든다.
3) 차례를 넘긴다.
5. 1~4를 반복하다가 누군가가 점수를 받으면 라운드가 종료된다. 수집가와 추측자를 교체하고 새 라운드 시작.
● 점수 요약
수집가
-4점 : 추측 실패
-6점 : 묶음 완성
추측자
-1점 : 색 또는 역할 추측 성공
-2점 : 묶음 완성
-3점 : 덱 다 떨어짐
-5점 : 색 그리고 역할 추측 성공
● 팁
수집가는 카드를 6장을 모으고 나면 덱이 떨어지므로 적절하게 블러핑한다.
추측자는 수집가가 같은 특성 3장을 모았을 때 반드시 추리를 하되 블러핑인 것 같다면 덱이 떨어지도록 기다린다.
6f1bc956b20d379c31117dc36bc8dbd5197b215d
1412
1411
2022-07-30T13:02:47Z
Samosal
8196
wikitext
text/x-wiki
● 모든 카드는 2가지 '특성'을 가지고 있다.
-색깔 : 빨강 또는 파랑
-역할 : 여자 또는 호랑이
(예 : 빨강호랑이, 빨강여자, 파랑여자)
● 구성물 :
-정체카드 4장(빨여, 빨호, 파여, 파호 각 1장씩)
-단서카드 12장(빨여, 빨호, 파여, 파호 각 3장씩)
-와일드카드 2장(여/호, 빨/파 각 1장씩)
(예 : 여/호 카드는 여자 or 호랑이로 사용할 수 있다.)
● '묶음'이란 자신의 정체와 특성 1가지가 같은 4장의 카드들을 말한다.
(예 : 나의 정체는 파랑호랑이인데 파랑카드 4장을 모으거나 호랑이카드 4장을 모으면 된다. 호랑이카드 4장 = 빨호, 파호, 빨호, 여/호)
● 게임 목표 : 10점 달성하면 승리
'수집가'는 자신의 정체와 같은 묶음(4장)을 모으거나 추측자가 자신의 정체를 추리하는 것을 실패하도록 유도한다.
'추측자'는 수집가의 정체를 맞추거나 수집가보다 먼저 묶음을 만들면 된다.
● 라운드 세팅 :
1명은 수집가, 다른 1명은 추측자를 맡고 정체카드를 랜덤으로 1장씩 받는다.
단서카드와 와일드카드를 섞어 덱을 만든 후 4장을 공개한다.
수집가부터 행동을 시작한다.
● 라운드 순서 :
1. 수집가는 공개된 단서카드 4장 중에서 1장을 가져오고, 즉시 덱에서 1장을 공개한다.
2. 수집가는 묶음을 만들거나 차례를 넘긴다.
1) 묶음을 만든다. 자신의 정체와 특성 1가지가 같은 4장의 카드들을 모았다면 6점을 받고 라운드 종료.
2) 차례를 넘긴다.
3. 추측자는 정체를 추리하거나 묶음을 만들거나 공개된 카드 1장을 버린다(초반에는 카드 버리기).
1) 수집가의 정체를 추리한다.
(안전하게) 역할 또는 색깔을 맞추면 1점을 받고 라운드 종료.
(확실하면) 역할 그리고 색깔을 맞추면 5점을 받고 라운드 종료.
(실패)하나라도 틀리면 수집가가 4점을 받고 라운드 종료.
2) 묶음을 만든다.
수집가가 모은 카드 중에서 자신의 정체와 같은 묶음이 있다면 2점을 받고 라운드 종료.
3) 추측자는 공개된 단서카드 4장 중에서 1장을 버리고, 즉시 덱에서 1장을 공개한다. 이때 덱이 다 떨어지면 3점을 받고 라운드 종료.
4. 추측자는 정체를 추리하거나 묶음을 만들거나 차례를 넘긴다.
1) 수집가의 정체를 추리한다.
2) 묶음을 만든다.
3) 차례를 넘긴다.
5. 1~4를 반복하다가 누군가가 점수를 받으면 라운드가 종료된다. 수집가와 추측자를 교체하고 새 라운드 시작.
● 점수 요약 :
수집가
-4점 : 추측 실패
-6점 : 묶음 완성
추측자
-1점 : 색 또는 역할 추측 성공
-2점 : 묶음 완성
-3점 : 덱 다 떨어짐
-5점 : 색 그리고 역할 추측 성공
● 팁 :
'수집가'는 카드를 6장을 모으고 나면 덱이 떨어지므로 적절하게 블러핑한다.
'추측자'는 수집가가 같은 특성 3장을 모았을 때 반드시 추리를 하되 블러핑인 것 같다면 덱이 떨어지도록 기다린다.
f25ac7870288d5b120d158949b4555da8d8f589e
1413
1412
2022-07-30T13:03:48Z
Samosal
8196
wikitext
text/x-wiki
● 모든 카드는 2가지 '특성'을 가지고 있다.
-색깔 : 빨강 또는 파랑
-역할 : 여자 또는 호랑이
(예 : 빨강호랑이, 빨강여자, 파랑여자)
● 구성물 :
-정체카드 4장(빨여, 빨호, 파여, 파호 각 1장씩)
-단서카드 12장(빨여, 빨호, 파여, 파호 각 3장씩)
-와일드카드 2장(여/호, 빨/파 각 1장씩)
(예 : 여/호 카드는 여자 or 호랑이로 사용할 수 있다.)
● '묶음'이란 자신의 정체와 특성 1가지가 같은 4장의 카드들을 말한다.
(예 : 나의 정체는 파랑호랑이인데 파랑카드 4장을 모으거나 호랑이카드 4장을 모으면 된다. 호랑이카드 4장 = 빨호, 파호, 빨호, 여/호)
● 게임 목표 : 10점 달성하면 승리
'수집가'는 자신의 정체와 같은 묶음(4장)을 모으거나 추측자가 자신의 정체를 추리하는 것을 실패하도록 유도한다.
'추측자'는 수집가의 정체를 맞추거나 수집가보다 먼저 묶음을 만들면 된다.
● 라운드 세팅 :
1명은 수집가, 다른 1명은 추측자를 맡고 정체카드를 랜덤으로 1장씩 받는다.
단서카드와 와일드카드를 섞어 덱을 만든 후 4장을 공개한다.
수집가부터 행동을 시작한다.
● 라운드 순서 :
1. 수집가는 공개된 단서카드 4장 중에서 1장을 가져오고, 즉시 덱에서 1장을 공개한다.
2. 수집가는 묶음을 만들거나 차례를 넘긴다.
1) 묶음을 만든다. 자신의 정체와 특성 1가지가 같은 4장의 카드들을 모았다면 6점을 받고 라운드 종료.
2) 차례를 넘긴다.
3. 추측자는 정체를 추리하거나 묶음을 만들거나 공개된 카드 1장을 버린다(초반에는 카드 버리기).
1) 수집가의 정체를 추리한다.
(안전하게) 역할 또는 색깔을 맞추면 1점을 받고 라운드 종료.
(확실하면) 역할 그리고 색깔을 맞추면 5점을 받고 라운드 종료.
(실패)하나라도 틀리면 수집가가 4점을 받고 라운드 종료.
2) 묶음을 만든다.
수집가가 모은 카드 중에서 자신의 정체와 같은 묶음이 있다면 2점을 받고 라운드 종료.
3) 추측자는 공개된 단서카드 4장 중에서 1장을 버리고, 즉시 덱에서 1장을 공개한다. 이때 덱이 다 떨어지면 3점을 받고 라운드 종료.
4. 추측자는 정체를 추리하거나 묶음을 만들거나 차례를 넘긴다.
1) 수집가의 정체를 추리한다.
2) 묶음을 만든다.
3) 차례를 넘긴다.
5. 1~4를 반복하다가 누군가가 점수를 받으면 라운드가 종료된다. 수집가와 추측자를 교체하고 새 라운드 시작.
● 점수 요약 :
-수집가
4점 : 추측 실패
6점 : 묶음 완성
-추측자
1점 : 색 또는 역할 추측 성공
2점 : 묶음 완성
3점 : 덱 다 떨어짐
5점 : 색 그리고 역할 추측 성공
● 팁 :
'수집가'는 카드를 6장을 모으고 나면 덱이 떨어지므로 적절하게 블러핑한다.
'추측자'는 수집가가 같은 특성 3장을 모았을 때 반드시 추리를 하되 블러핑인 것 같다면 덱이 떨어지도록 기다린다.
aff25c38434dde6e62afae3da16e6f326d270e81
1414
1413
2022-07-30T13:05:52Z
Samosal
8196
wikitext
text/x-wiki
● 모든 카드는 2가지 '특성'을 가지고 있다.
-색깔 : 빨강 또는 파랑
-역할 : 여자 또는 호랑이
(예 : 빨강호랑이, 빨강여자, 파랑여자)
● 구성물 :
-정체카드 4장(빨여, 빨호, 파여, 파호 각 1장씩)
-단서카드 12장(빨여, 빨호, 파여, 파호 각 3장씩)
-와일드카드 2장(여/호, 빨/파 각 1장씩)
(예 : 여/호 카드는 여자 or 호랑이로 사용할 수 있다.)
● '묶음'이란 자신의 정체와 특성 1가지가 같은 4장의 카드들을 말한다.
(예 : 나의 정체는 파랑호랑이인데 파랑카드 4장을 모으거나 호랑이카드 4장을 모으면 된다. 호랑이카드 4장 = 빨호, 파호, 빨호, 여/호)
● 게임 목표 : 10점 달성하면 승리
'수집가'는 자신의 정체와 같은 묶음(4장)을 모으거나 추측자가 자신의 정체를 추리하는 것을 실패하도록 유도한다.
'추측자'는 수집가의 정체를 맞추거나 수집가보다 먼저 묶음을 만들면 된다.
● 라운드 세팅 :
1명은 수집가, 다른 1명은 추측자를 맡고 정체카드를 랜덤으로 1장씩 받는다.
단서카드와 와일드카드를 섞어 덱을 만든 후 4장을 공개한다.
수집가부터 행동을 시작한다.
● 라운드 순서 :
1. 수집가는 공개된 단서카드 4장 중에서 1장을 가져오고, 즉시 덱에서 1장을 공개한다.
2. 수집가는 묶음을 만들거나 차례를 넘긴다.
1) 묶음을 만든다. 자신의 정체와 특성 1가지가 같은 4장의 카드들을 모았다면 6점을 받고 라운드 종료.
2) 차례를 넘긴다.
3. 추측자는 정체를 추리하거나 묶음을 만들거나 공개된 카드 1장을 버린다(초반에는 카드 버리기).
1) 수집가의 정체를 추리한다.
(안전하게) 역할 또는 색깔을 맞추면 1점을 받고 라운드 종료.
(확실하면) 역할 그리고 색깔을 맞추면 5점을 받고 라운드 종료.
(실패)하나라도 틀리면 수집가가 4점을 받고 라운드 종료.
2) 묶음을 만든다.
수집가가 모은 카드 중에서 자신의 정체와 같은 묶음이 있다면 2점을 받고 라운드 종료.
3) 추측자는 공개된 단서카드 4장 중에서 1장을 버리고, 즉시 덱에서 1장을 공개한다.
이때 덱이 다 떨어지면 3점을 받고 라운드 종료.
4. 추측자는 정체를 추리하거나 묶음을 만들거나 차례를 넘긴다.
1) 수집가의 정체를 추리한다.
2) 묶음을 만든다.
3) 차례를 넘긴다.
5. 1~4를 반복하다가 누군가가 점수를 받으면 라운드가 종료된다.
수집가와 추측자를 교체하고 새 라운드 시작.
● 점수 요약 :
'수집가'
4점 : 추측 실패
6점 : 묶음 완성
'추측자'
1점 : 색 또는 역할 추측 성공
2점 : 묶음 완성
3점 : 덱 다 떨어짐
5점 : 색 그리고 역할 추측 성공
● 팁 :
'수집가'는 카드를 6장을 모으고 나면 덱이 떨어지므로 적절하게 블러핑한다.
'추측자'는 수집가가 같은 특성 3장을 모았을 때 반드시 추리를 하되 블러핑인 것 같다면 덱이 떨어지도록 기다린다.
eca637db5e749a2464ca770f4bd064e4b8d3de3b
1415
1414
2022-07-30T13:09:08Z
Samosal
8196
wikitext
text/x-wiki
● 모든 카드는 2가지 '특성'을 가지고 있다.
-색깔 : 빨강 또는 파랑
-역할 : 여자 또는 호랑이
(예 : 빨강호랑이, 빨강여자, 파랑여자)
● 구성물 :
-정체카드 4장(빨여, 빨호, 파여, 파호 각 1장씩)
-단서카드 12장(빨여, 빨호, 파여, 파호 각 3장씩)
-와일드카드 2장(여/호, 빨/파 각 1장씩)
(예 : 여/호 카드는 여자 or 호랑이로 사용할 수 있다.)
● '묶음'이란 자신의 정체와 특성 1가지가 같은 4장의 카드들을 말한다.
(예 : 나의 정체는 파랑호랑이인데 파랑카드 4장을 모으거나 호랑이카드 4장을 모으면 된다. 호랑이카드 4장 = 빨호, 파호, 빨호, 여/호)
● 게임 목표 : 10점 달성하면 승리
'수집가'는 자신의 정체와 같은 묶음(4장)을 모으거나 추측자가 자신의 정체를 추리하는 것을 실패하도록 유도한다.
'추측자'는 수집가의 정체를 맞추거나 수집가보다 먼저 묶음을 만들면 된다.
● 라운드 세팅 :
1명은 수집가, 다른 1명은 추측자를 맡고 정체카드를 랜덤으로 1장씩 받는다.
단서카드와 와일드카드를 섞어 덱을 만든 후 4장을 공개한다.
수집가부터 행동을 시작한다.
● 라운드 순서 :
1. 수집가는 공개된 단서카드 4장 중에서 1장을 가져오고, 즉시 덱에서 1장을 공개한다.
2. 수집가는 묶음을 만들거나 차례를 넘긴다.
1) 묶음을 만든다.
자신의 정체와 특성 1가지가 같은 4장의 카드들을 모았다면 6점을 받고 라운드 종료.
2) 차례를 넘긴다.
3. 추측자는 정체를 추리하거나 묶음을 만들거나 공개된 카드 1장을 버린다(초반에는 카드 버리기).
1) 수집가의 정체를 추리한다.
(안전하게) 역할 또는 색깔을 맞추면 1점을 받고 라운드 종료.
(확실하면) 역할 그리고 색깔을 맞추면 5점을 받고 라운드 종료.
(실패)하나라도 틀리면 수집가가 4점을 받고 라운드 종료.
2) 묶음을 만든다.
수집가가 모은 카드 중에서 자신의 정체와 같은 묶음이 있다면 2점을 받고 라운드 종료.
3) 추측자는 공개된 단서카드 4장 중에서 1장을 버리고, 즉시 덱에서 1장을 공개한다.
이때 덱이 다 떨어지면 3점을 받고 라운드 종료.
4. 추측자는 정체를 추리하거나 묶음을 만들거나 차례를 넘긴다.
1) 수집가의 정체를 추리한다.
2) 묶음을 만든다.
3) 차례를 넘긴다.
5. 1~4를 반복하다가 누군가가 점수를 받으면 라운드가 종료된다.
수집가와 추측자를 교체하고 새 라운드 시작.
● 점수 요약 :
'수집가'
4점 : 추측 실패
6점 : 묶음 완성
'추측자'
1점 : 색 또는 역할 추측 성공
2점 : 묶음 완성
3점 : 덱 다 떨어짐
5점 : 색 그리고 역할 추측 성공
● 팁 :
'수집가'는 카드를 6장을 모으고 나면 덱이 떨어지므로 적절하게 블러핑한다.
'추측자'는 수집가가 같은 특성 3장을 모았을 때 반드시 추리를 하되 블러핑인 것 같다면 덱이 떨어지도록 기다린다.
54684fbeeea2017b7d8314bd3a212cd5a0cc0889
1416
1415
2022-07-30T13:13:51Z
Samosal
8196
wikitext
text/x-wiki
● 모든 카드는 2가지 '특성'을 가지고 있다.
-색깔 : 빨강 또는 파랑
-역할 : 여자 또는 호랑이
(예 : 빨강호랑이, 빨강여자, 파랑여자)
● 구성물 :
-정체카드 4장(빨여, 빨호, 파여, 파호 각 1장씩)
-단서카드 12장(빨여, 빨호, 파여, 파호 각 3장씩)
-와일드카드 2장(여/호, 빨/파 각 1장씩)
(예 : 여/호 카드는 여자 or 호랑이로 사용할 수 있다.)
● '묶음'이란 자신의 정체와 특성 1가지가 같은 4장의 카드들을 말한다.
(예 : 나의 정체는 파랑호랑이인데 파랑카드 4장을 모으거나 호랑이카드 4장을 모으면 된다. 호랑이카드 4장 = 빨호, 파호, 빨호, 여/호)
● 게임 목표 : 10점 달성하면 승리
'수집가'는 자신의 정체와 같은 묶음(4장)을 모으거나 추측자가 자신의 정체를 추리하는 것을 실패하도록 유도한다.
'추측자'는 수집가의 정체를 맞추거나 수집가보다 먼저 묶음을 만들면 된다.
● 라운드 세팅 :
1명은 수집가, 다른 1명은 추측자를 맡고 정체카드를 랜덤으로 1장씩 받는다.
단서카드와 와일드카드를 섞어 덱을 만든 후 4장을 공개한다.
수집가부터 행동을 시작한다.
● 라운드 순서 :
1. 수집가는 공개된 단서카드 4장 중에서 1장을 가져오고, 즉시 덱에서 1장을 공개한다.
2. 수집가는 묶음을 만들거나 차례를 넘긴다.
1) 묶음을 만든다.
자신의 정체와 특성 1가지가 같은 4장의 카드들을 모았다면 6점을 받고 라운드 종료.
2) 차례를 넘긴다.
3. 추측자는 정체를 추리하거나 묶음을 만들거나 공개된 카드 1장을 버린다(초반에는 카드 버리기).
1) 수집가의 정체를 추리한다.
(안전하게) 색깔 또는 역할을 맞추면 1점을 받고 라운드 종료.
(확실하면) 색깔 그리고 역할을 맞추면 5점을 받고 라운드 종료.
(실패)하나라도 틀리면 수집가가 4점을 받고 라운드 종료.
2) 묶음을 만든다.
수집가가 모은 카드 중에서 자신의 정체와 같은 묶음이 있다면 2점을 받고 라운드 종료.
3) 추측자는 공개된 단서카드 4장 중에서 1장을 버리고, 즉시 덱에서 1장을 공개한다.
이때 덱이 다 떨어지면 3점을 받고 라운드 종료.
4. 추측자는 정체를 추리하거나 묶음을 만들거나 차례를 넘긴다.
1) 수집가의 정체를 추리한다.
2) 묶음을 만든다.
3) 차례를 넘긴다.
5. 1~4를 반복하다가 누군가가 점수를 받으면 라운드가 종료된다.
수집가와 추측자를 교체하고 새 라운드 시작.
● 점수 요약 :
'수집가'
4점 : 추측 실패
6점 : 묶음 완성
'추측자'
1점 : 색깔 또는 역할 추측 성공
2점 : 묶음 완성
3점 : 덱 다 떨어짐
5점 : 색깔 그리고 역할 추측 성공
● 팁 :
'수집가'는 카드를 6장을 모으고 나면 덱이 떨어지므로 적절하게 블러핑한다.
'추측자'는 수집가가 같은 특성 3장을 모았을 때 반드시 추리를 하되 블러핑인 것 같다면 덱이 떨어지도록 기다린다.
af1903d485139a10c8515dc31cbdccadd0efb19b
Gamehelpmarrakech
0
235
1417
2022-08-07T15:23:37Z
Yongii
8277
Korean translation
wikitext
text/x-wiki
* 게임 목표
각각의 판매상은 게임 종료 시점에 자신의 러그가 가장 많이 보이게 하는 것을 필요로 합니다.
각 판매상이 모든 러그를 소진했을 때, 자신 소유의 러그가 가장 많이 보이는 사람이 승리합니다.
* 게임 하는 법
각각의 플레이어는 30 디르함과 12 개의 동일 색상의 러그를 가지고 시작합니다.
매 턴마다 플레이어는 아래 세 가지의 행동을 해야 합니다.
1. 아쌈을 움직이세요.
2. 만약 상대의 러그를 밟았다면, 돈을 지불합니다.
3. 아쌈의 인접 타일에 러그를 배치합니다.
* 아쌈을 움직이기
해당 차례의 플레이어는 주사위를 던지기 전에 아쌈이 움직일 방향을 선택합니다. 주사위는 6면체를 사용합니다.
아쌈은 방향을 유지하거나, 90° 회전할 수 있습니다. 180° 회전은 불가능합니다.
그 후 주사위를 던집니다. 주사위에 그려진 슬리퍼의 갯수가 아쌈이 움직일 타일 수를 결정합니다.
아쌈은 대각으로 이동할 수 없으며, 주사위를 던지기 전에 설정한 방향으로만 직진합니다.
만약 아쌈이 마켓 밖으로 나간다면 마켓 밖에 표시된 방향지시를 따라 회전하여 움직임을 계속합니다.
* 러그 배치하기
플레이어는 아쌈이 움직이고 난 뒤, 아쌈의 옆 타일에 러그를 배치합니다. 러그를 배치할 때, 상대방의 러그 2칸을 모두 가릴 수는 없습니다. 러그는 오직 두 칸의 빈 타일 또는 한 칸의 빈 타일과 다른 한 칸의 러그 위에만 배치할 수 있습니다.
* 플레이어간 비용 지불
만약 아쌈이 상대의 러그를 밟는다면, 해당 차례의 플레이어는 러그의 주인에게 비용을 지불해야 합니다. 비용은 연결된 같은 색상의 러그 수만큼 지불합니다. 오직 직선으로 인접한 러그의 숫자만 계산하며, 대각으로 연결된 러그는 포함되지 않습니다.
또한, 한 플레이어의 러그라고 할 지라도 밟은 러그와 인접한 러그의 색상이 다르다면 다른 색상의 러그에 대한 비용은 계산에서 제외됩니다.
예를 들어) 당신의 아쌈이 제가 배치한 총 4칸이 연결된 노란색 러그를 밟았다면, 4 디르함을 지불합니다. 만약 4칸의 노란색 러그가 연결되어 있고, 인접한 타일에 제 소유의 붉은색 러그가 존재한다고 하더라도 오직 4 디르함만 지불합니다.
* 게임 종료
게임은 모든 플레이어의 모든 러그가 소진되면 종료됩니다. 모든 반 칸의 러그는 1 디르함으로 계산됩니다. 계산 이후, 가장 많은 디르함을 가지고 있는 플레이어가 승리합니다.
또는 어떤 플레이어가 디르함을 지불할 수 있는 여력이 없을 때 종료됩니다.
예를 들어) 당신과 저는 각각 30 디르함을 보유하고 있고, 제 러그가 2칸, 당신의 러그가 1칸 존재한다면 제 승리입니다.
저는 30 디르함, 당신은 25 디르함을 가지고 있고, 제 러그가 5칸, 당신의 러그가 15칸 있다면, 당신의 승리입니다.
* 1대1 대결일 결우
두 명의 플레이어가 게임하는 경우 각각 두 개의 다른 색의 러그를 총 24장씩 소유합니다. 배치할 러그의 색상은 무작위로 선택됩니다.
예를 들어) 이전 차례에 당신은 빨간색 러그를 배치했고, 이번 차례에는 노란색을 배치하게 될 수도, 빨간색을 유지하게 될 수도 있습니다.
ee8aad92187c3cfb30d6b72fcd695d7d307619e6
Gamehelplama
0
197
1418
1288
2022-09-02T08:54:43Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요==
카드를 적게 들고 있을수록 좋지만, 라마를 남기지는 마세요.
==승리조건==
게임은 어느 한 플레이어가 -40점에 도달하면 종료됩니다.
이 때, 점수가 가장 높은 사람이 승리하게됩니다.
==게임 방법==
라마는 4명의 플레이어가 하는 카드게임입니다. 1~6,라마를 각각 8장씩 총 56장의 카드를 사용합니다.
카드의 크기는 라마, 1, 2, 3, 4, 5, 6, 라마입니다.
===라운드 시작===
모든 플레이어는 6장의 카드를 받고 카드뭉치에서 한장을 뒤집어 바닥에 놓습니다.
===라운드 진행===
자신의 차례가 되면 카드를 1장 내거나 1장 받거나 라운드에 빠지는 것 중 한가지 행동을 해야합니다.
1. 카드를 내려면 바닥의 카드와 같은 카드거나 크기가 1 더 높은 카드여야 합니다.
2. 카드뭉치에 카드가 없으면 카드를 받을 수 없습니다.
3. 라운드에서 빠지면 해당 플레이어의 차례는 라운드가 끝날 때까지 건너뜁니다.
4. 1명을 제외한 모든 플레이어가 라운드에서 빠지면 더 이상 카드를 뽑을 수 없습니다.
5. 1명을 제외한 모든 플레이어가 라운드에서 빠지면 남은 한사람이 연속으로 차례를 진행합니다.
6. 1명을 제외한 모든 플레이어가 라운드에서 빠졌을 때 모든 카드를 연속해서 낼 수 있는 상황이 되면 모든 카드를 내려놓는 동작이 활성화됩니다.
===라운드 종료===
모든 플레이어가 라운드에서 빠지거나 한명의 플레이어가 0장의 카드를 갖고 있을 경우 라운드가 종료됩니다.
라운드 종료 후 점수계산이 이뤄집니다.
===점수 계산===
1. 숫자 카드를 가지고 있으면 해당 숫자만큼 감점이 됩니다. 이 때, 같은 숫자카드를 몇 장을 가지고 있든 한번만 감점됩니다.
2. 라마 카드를 가지고 있으면 10점이 감점됩니다. 이 때, 라마 카드를 몇 장을 가지고 있든 한번만 감점됩니다.
3. 라운드 종료시 0장의 카드를 가지고 있으면 점수를 얻습니다.
자신의 점수가 -10점 이하면 10점을 얻습니다.
자신의 점수가 -1 ~ -9점이면 1점을 얻습니다.
자신의 점수가 0점 이상이면 0점을 얻습니다.
4ff547083d8e26338a14c5370190b1d7debe6a67
Gamehelpsolo
0
236
1419
2022-09-10T15:19:38Z
Rksehddms12
8376
새 문서: 솔로는 간단한 게임으로, 당신이 가장 먼저 손에 있는 모든 카드를 해야 한다. 모든 카드는 특정한 양의 포인트의 가치가 있다. 각 라운드...
wikitext
text/x-wiki
솔로는 간단한 게임으로, 당신이 가장 먼저 손에 있는 모든 카드를 해야 한다. 모든 카드는 특정한 양의 포인트의 가치가 있다. 각 라운드가 끝날 때마다 해당 포인트의 총 수는 라운드에서 승리하지 않은 경우 라운드를 시작할 때 사용한 총 점수에서 차감됩니다.
특수 카드
스왑 카드(직접): 원하는 플레이어의 손과 손 전체를 교환할 수 있습니다.
스왑 카드(회전): 회색 스와프 카드는 현재 플레이 순서에 따라 모든 플레이어의 손을 회전시킵니다. 카드의 이미지는 항상 시계 방향으로 표시되므로 오해를 일으킬 수 있습니다. 게임 순서가 시계 방향일 경우 카드가 시계 반대 방향으로 바뀝니다. 이 카드 이후에 어떤 카드든 플레이할 수 있습니다.
건너뛰기: 다음 플레이어를 건너뜁니다.
더하기 2: 이것은 다음 순서의 플레이어가 2장의 카드를 뽑게 한다. 액티브 플러스 2(하나는 당신을 목표로 플레이)에서 플레이하여 다음 플레이어가 4를 그리게 할 수 있습니다. 이러한 쌓기 효과는 플레이어가 Plus Two를 플레이할 수 없을 때까지 무한히 지속됩니다(0+2= Plus 2, 2+2= Plus 4, 4+2= Plus 6 등).
와일드: 색상을 변경할 수 있습니다.
와일드 플러스 4: 다음 플레이어가 4장의 카드를 그리게 하는 동시에 색을 바꿀 수 있습니다. 더하기 2처럼, 효과는 쌓일 수 있다.
카드놀이
카드를 재생하려면 카드를 폐기 파일 상단에 있는 색상 또는 숫자/기호와 일치해야 합니다. 스와프 카드(회전)와 두 가지 유형의 와일드 카드는 예외이며, 모든 장치에서 재생할 수 있습니다.
뛰어들기
방금 재생한 카드와 동일한 카드(색상 및 숫자/기호)가 있으면 즉시 재생할 수 있습니다. 사용자와 원래 카드의 플레이어 사이에 있는 모든 플레이어는 건너뜁니다.
솔로
한 장의 카드를 손에 쥐게 되는 동작을 수행하기 전에 "solo"를 호출해야 합니다. 그렇지 않으면 카드 두 장을 뽑아야 한다.
채점
액면가 - 1-9
10 - 방향 변경
20 - 건너뛰기
30 - 2번 추첨, 다른 플레이어와 카드 교환
40 - 차례로 카드 교환, 색상 선택
50 - 그리기 4 + 색상 선택
시행되지 않은 규칙
링크드 룰북은 게임의 BGA 구현보다 최신이며, 적어도 하나의 규칙 개정판을 반영한다. 특히 BGA에서는 규칙집에 언급된 "트리플 +" 규칙이 지원되지 않습니다.
0c4d8684e32573557c043b8ddb4c80c5105cf139
Gamehelpfruitpicking
0
215
1420
1363
2022-10-10T05:53:40Z
Ufm
6353
wikitext
text/x-wiki
== 게임의 목표 ==
과일을 팔아 판매증서를 모으고, 세트를 완성하세요.
== 차례 개요 ==
=== 씨앗 심기 ===
농장을 하나 고르고, 거기 있는 모든 씨앗 토큰을 집습니다. 시계방향으로 한 칸씩 이동하며 씨앗 토큰을 하나씩 내려 놓습니다.
''참고: 매우 드물지만 자신의 차례가 시작되었을 때 보관소나 저장창고에만 씨앗 토큰이 있고 어떤 농장에도 씨앗 토큰이 없는 경우가 있을 수 있습니다.''
''이때는 씨앗 심기나 일할 곳 행동을 하지 않고, 보관소(나 부족하면 저장창고)에 있는 씨앗 토큰 3개를 꺼내 저장창고 우측에 있는 농장 3곳에 1개씩 놓은 다음 차례를 마칩니다.''
=== 일할 곳 ===
마지막으로 씨앗 토큰을 내려 놓은 곳이 이번에 일할 곳이 됩니다. 이제 물 뿌리기나 과일 판매 중에서 하나를 고르세요.
마지막 씨앗 토큰이 저장창고 위에 놓이면 즉시 씨앗 심기를 한 번 더 진행합니다. 행동이 가능할 때 행동을 넘길 수는 없습니다.
=== 물 뿌리기나 과일 판매 ===
==== 물 뿌리기 ====
일할 곳에 그려진 과일 혹은 빗방울의 개수만큼, 보관소에서 씨앗 토큰을 가져와 일할 곳에 올립니다.
==== 과일 판매 ====
일할 곳에 그려진 과일과 같은 그림의 과일과 같은 그림의 과일을 시장섬에서 가져옵니다.
알맞은 개수의 씨앗 토큰을 저장창고에서 집어 보관소로 되돌리고, 일할 곳에 있던 모든 씨앗 토큰도 보관소로 되돌립니다.
=== 다음 플레이어 차례로 ===
다음 사람에게 차례가 넘어갑니다.
=== 게임 종료 ===
누군가 시장섬에 표시된 4개의 세트 중 하나를 달성하면, 이번 라운드까지 마치고 게임이 끝납니다.
==== 세트의 종류 ====
* 하우스: 2종류의 판매증서를 각각 2장, 3장 모음
* 독점판매: 1종류의 판매증서를 4장 모음
* 과일 꾸러미: 3종류의 판매증서를 2장씩 모음
* 백화점: 5종류의 판매증서를 1장씩 모음
== 변형 규칙 ==
=== 어린이 농부 ===
시장섬을 사용하지 않고, 판매증서를 섞고 맨 위 3장을 앞면이 보이게 바닥에 놓아 시장을 꾸립니다. 자릿세는 없습니다.
누구든 판매증서를 먼저 5장 모은 사람이 있다면, 그 사람이 즉시 이깁니다.
=== 무작위 설정 ===
게임을 준비할 때 모든 플레이어가 각자 농장카드를 섞어 저장창고의 다음 칸부터 시계 방향으로 카드를 놓습니다.
=== 1인 플레이 ===
==== 준비 ====
판매증서 중 과일별로 1장씩을 꺼내 5장으로 구성된 더미를 만듭니다. 이 더미를 섞고, 맨 위 판매증서를 앞면이 보이게 바닥에 놓습니다.
==== 게임 진행 ====
판매증서는 항상 1장만 앞면으로 놓입니다.
과일 판매를 할 때, 내야 할 씨앗 토큰과 저장창고에 남은 씨앗 토큰을 보관소에 되돌리지 않고 모두 제거하여 이번 게임에서 다시는 사용하지 않습니다.
일할 곳의 씨앗 토큰은 보관소로 되돌립니다.
그 후 새로운 판매증서를 앞면으로 바닥에 놓고 게임을 계속합니다.
==== 게임 종료 ====
아래의 3가지 조건 중 하나라도 만족했다면 즉시 게임이 종료됩니다.
* 보관소에 씨앗이 남아있지 않는 경우 (패배)
* 저장창고에만 씨앗이 있고 농장에는 씨앗이 없는 경우 (패배)
* 판매증서 5장을 모두 모은 경우 (승리)
판매증서 5장을 모두 모았다면 게임에서 승리합니다!
9a5f84de19fa35dcbf170184852a593cb1dacb45
Gamehelpkoikoi
0
195
1421
1279
2022-10-21T07:08:51Z
Yehuin
8473
wikitext
text/x-wiki
=코이코이=
코이코이는 일본에서 가장 많이 하는 화투 게임 중 하나입니다. 화투는 한 해의 12개월에 따라 자연을 묘사한 일본의 전통 카드 묶음입니다.
자기 손이나 카드 더미에서 바닥에 깔린 패와 같은 달의 패를 내야 패를 가져와 (특정 조합을 구성해 점수를 내는 족보인) 역을 만들 수 있습니다.
역을 만들면 멈추고 그 시점의 점수를 획득하거나, '코이코이'를 선언하고 계속 진행해 보다 강력한 역의 완성을 시도할 수 있습니다.
=게임방법=
2명의 플레이어는 각각 50 일본엽전을 가지고 시작합니다.
2명의 플레이어는 각각 8장의 패를 들고 바닥에도 8장의 패를 깔고 시작합니다.
2명의 플레이어는 각각 한턴씩 진행하는 방식입니다.
각각의 턴에서 패에서 한장을 바닥에 내려놓고 패 뭉치에서 한장 집어서 바닥에 내려놓습니다.
내려놓는 카드와 바닥에 있는 카드가 같은 달의 패면 가져올 수 있습니다.
바닥에 두장의 같은 달의 패가 있을 때는 둘 중 하나만 가져옵니다.
바닥에 세장의 같은 달의 패가 있을 때는 모든 카드를 가져옵니다.
가져온 카드의 조합, 즉 역에 따라 문(점수)을 획득할 수 있습니다.
=역의 종류=
게임중 아이콘을 누르면 역의 종류와 해당 역의 문을 볼 수 있는 리스트가 나오며, 리스트의 최하단에 12개월의 패를 알수 있습니다.
=기타=
1. 2명의 플레이어는 각각 50 일본엽전을 가지고 시작합니다.
2. 한 판의 게임은 6달(라운드) 또는 12달로 이루어져 있습니다.
3. 자신의 턴이 끝났을 때 문을 추가하는데 성공하면 코이코이나 쇼부를 선택할 수 있습니다.
쇼부를 선택하면 그 즉시 달의 진행이 끝나며 자신의 문만큼 상대의 일본 엽전을 가져올 수 있습니다.
코이코이를 선택하면 해당 달의 진행을 속행하며 다음 문 추가 때 코이코이선택 또는 쇼부를 선택할 수 있습니다.
4. 상대의 코이코이 이후 자신이 쇼부를 내어 달의 진행을 마무리할 경우 문이 두배가 되는데 이를 코이코이가에시(こいこい返し)라고 한다.
5. 쇼부를 내었을 때 7문이 넘으면 점수가 두배가 되는데 이를 바이츠케(倍付け)라고 한다.
6. 쇼부가 나지 않고 모든 플레이어가 패를 다 사용하면 먼저 시작한 플레이어가 승리하며 6문을 가져가느데 이를 친권이라고 한다.
7. 자신의 일본엽전을 모두 잃거나 게임이 종료했을 때 상대보다 일본엽전이 적으면 진다.
35363d9455e3c6962033089631160df0ad111cee
Gamehelpseotda
0
237
1422
2022-10-26T15:06:12Z
Ufm
6353
새 문서: ==Rules clarification== * BGA implementation follows standard no-limit Poker betting rules. Thus, players are not limited to certain options during betting rounds. Also, 9 and 4 pena...
wikitext
text/x-wiki
==Rules clarification==
* BGA implementation follows standard no-limit Poker betting rules. Thus, players are not limited to certain options during betting rounds. Also, 9 and 4 penalty and Pair bonus do not exist.
* 9 and 4 is treated as a Sum of 3 when a rematch is not possible or not needed (the latter happens if all remaining players have a hand equal to or less than Sum of 3).
* Even if a Pair hunter / Bright Pair hunter fails to win a round, it is still treated as a hand between Pair of 10 - 9 / Bright Pair of 3 and 8 - 1 and 8 if at least one remaining opponent holds a Pair below 10 / a Bright Pair except 3 and 8. This is relevant while resolving side pots.
* 9 and 4's rematch fee for folded players is equal to 50% of the highest bet in that round. The winner takes all rematch fees regardless of their bets (in other words, no side pots for rematch fees).
* During a rematch, each player receives the minimal number of cards and goes through only a single betting round.
* The strength of 3-card combinations: Three Brights > Five Birds > Ribbons > Three of a kind
Feel free to add basic rules here :)
e581dacffffad6f64ada2b88e2bd5951255efb15
1423
1422
2022-10-27T02:58:25Z
Ufm
6353
wikitext
text/x-wiki
==Rules clarification==
* BGA implementation follows no-limit Poker betting rules with ante. Thus, players are not limited to certain options during betting rounds. Also, 9 and 4 penalty and Pair bonus do not exist.
* 9 and 4 is treated as a Sum of 3 when a rematch is not possible or not needed (the latter happens if all remaining players have a hand equal to or less than Sum of 3).
* Even if a Pair hunter / Bright Pair hunter fails to win a round, it is still treated as a hand between Pair of 10 - 9 / Bright Pair of 3 and 8 - 1 and 8 if at least one remaining opponent holds a Pair below 10 / a Bright Pair except 3 and 8. This is relevant while resolving side pots.
* 9 and 4's rematch fee for folded players is equal to 50% of the highest bet in that round. The winner takes all rematch fees regardless of their bets (in other words, no side pots for rematch fees).
* During a rematch, each player receives the minimal number of cards and goes through only a single betting round.
* The strength of 3-card combinations: Three Brights > Five Birds > Ribbons > Three of a kind
Feel free to add basic rules here :)
7a97cdc2d8d692129eafb08eb9d8bb544f2ffb4f
1424
1423
2022-10-27T02:59:18Z
Ufm
6353
wikitext
text/x-wiki
Feel free to add basic rules here :)
==Rules clarification==
* BGA implementation follows no-limit Poker betting rules with ante. Thus, players are not limited to certain options during betting rounds. Also, 9 and 4 penalty and Pair bonus do not exist.
* 9 and 4 is treated as a Sum of 3 when a rematch is not possible or not needed (the latter happens if all remaining players have a hand equal to or less than Sum of 3).
* Even if a Pair hunter / Bright Pair hunter fails to win a round, it is still treated as a hand between Pair of 10 - 9 / Bright Pair of 3 and 8 - 1 and 8 if at least one remaining opponent holds a Pair below 10 / a Bright Pair except 3 and 8. This is relevant while resolving side pots.
* 9 and 4's rematch fee for folded players is equal to 50% of the highest bet in that round. The winner takes all rematch fees regardless of their bets (in other words, no side pots for rematch fees).
* During a rematch, each player receives the minimal number of cards and goes through only a single betting round.
* The strength of 3-card combinations: Three Brights > Five Birds > Ribbons > Three of a kind
0c50b4c0031d3c6ac399854c9873cefa7046d135
1425
1424
2022-10-27T05:11:12Z
Ufm
6353
wikitext
text/x-wiki
Feel free to add basic rules here :)
==Rules clarification==
* BGA implementation follows no-limit Poker betting rules with ante. Thus, players are not limited to certain options during betting rounds. Also, 9 and 4 penalty and Pair bonus do not exist.
* 9 and 4 is treated as a Sum of 3 when a rematch is not possible or not needed (the latter happens if all remaining players have a hand equal to or less than Sum of 3).
* Even if a Pair hunter / Bright Pair hunter fails to win a round, it is still treated as a hand between Pair of 10 - 9 / Bright Pair of 3 and 8 - 1 and 8 if at least one remaining opponent holds a Pair below 10 / a Bright Pair except 3 and 8. This is relevant while resolving side pots.
* 9 and 4's rematch fee for folded players is equal to 50% of the highest bet in that round. The winner takes all rematch fees regardless of their bets (in other words, no side pots for rematch fees).
* During a rematch, each player receives the minimal number of cards and goes through only a single betting round.
* The strength of 3-card combinations: Three Brights > Five Birds > Ribbons > Three of a kind
631aac3b9737b90106a58925dca458163602c64d
Gamehelpsasaki
0
238
1426
2022-11-02T12:05:43Z
Ufm
6353
새 문서: Feel free to add basic rules here :) == Rules clarification == * In this implementation, the holder of 3 of Hearts starts odd-numbered rounds and the holder of 3 of Spades starts ev...
wikitext
text/x-wiki
Feel free to add basic rules here :)
== Rules clarification ==
* In this implementation, the holder of 3 of Hearts starts odd-numbered rounds and the holder of 3 of Spades starts even-numbered rounds.
* Pair interceptions can be queued in advance. Double straight interceptions cannot as they are much more complex and too situation dependent to be queued.
* No partnership in 3 player mode. A player may double the round score before the round begins, then another player may redouble. However, the last player cannot redouble again (so x8 multiplier is impossible).
* Players cannot intercept their own singles but may counter-intercept their pairs after intercepting another player's single.
42c69649a2ba70a6fefaebff4e3f21aa08d71ea0
1427
1426
2022-11-02T13:25:50Z
Ufm
6353
wikitext
text/x-wiki
Feel free to add basic rules here :)
== Rules clarification ==
* In this implementation, the holder of 3 of Hearts starts odd-numbered rounds and the holder of 3 of Spades starts even-numbered rounds.
* Pair interceptions can be queued in advance. Double straight interceptions cannot as they are much more complex and too situational to be queued.
* No partnership in 3 player mode. A player may double the round score before the round begins, then another player may redouble. However, the last player cannot redouble again (so x8 multiplier is impossible).
* Players cannot intercept their own singles but may counter-intercept their pairs after intercepting another player's single.
a780203d68d902bab189554e161f0aa445d76a14
Tips sechsnimmt
0
239
1428
2022-12-05T21:47:49Z
SeongJK
8564
새 문서: 매우 낮고 높은 카드를 먼저 없애라. 연속된 마지막 카드 중 가장 낮은 카드가 높은 경우, 카드 아래에서 가능한 한 높은 카드를 선택합니...
wikitext
text/x-wiki
매우 낮고 높은 카드를 먼저 없애라.
연속된 마지막 카드 중 가장 낮은 카드가 높은 경우, 카드 아래에서 가능한 한 높은 카드를 선택합니다.
항상 마지막 카드 중 가장 낮은 카드보다 낮은 카드를 선택할 가능성을 고려하십시오. 그들은 어떤 줄을 선택할까요?
100대와 90대 초반에 3장 이상의 카드가 나오면 가장 높은 카드를 먼저 치지 마세요. 운이 좋다면 한 줄을 스스로 "잠글" 수 있을 것입니다. 어려운 선택을 피할 필요가 있을 때 사용하십시오.
만약 당신이 줄을 서야 한다면, 그것이 저렴할 때 그렇게 하도록 노력하세요.
어떤 카드를 할지 고민할 때마다, 알 수 없는 카드보다는 이미 알려진 패배를 선택하는 것이 더 나을 수도 있다는 것을 기억하세요. (즉, 2점을 획득하는 위험을 감수하거나, 그 선에서 어떤 합계가 나오더라도 - 이미 알고 있는 것을 선택하십시오.)
9b4abfd5ea709084b65c97b846658861b2ee381b
Tips yatzy
0
240
1429
2022-12-28T08:00:59Z
Eggfri
8619
새 문서: 일반적인 팁 및 통계. 상위 절반에게는 35pt 보너스가 정말 중요하다. 그것을 얻기 위해서는, 1에서 6까지, 총 63개의 종류 중 적어도 3개가 필요합니다. 하위 절반인 스리/포 어 카인드 앤 찬스의 경우, 당신은 총 17개 이상인 5개의 주사위의 평균보다 더 나은 점수를 얻고자 한다. 풀 하우스와 스트레이트스의 경우, 일찍 낚시를 하고 실패한 시도를 당신의 상위 절반...
wikitext
text/x-wiki
일반적인 팁 및 통계.
상위 절반에게는 35pt 보너스가 정말 중요하다. 그것을 얻기 위해서는, 1에서 6까지, 총 63개의 종류 중 적어도 3개가 필요합니다.
하위 절반인 스리/포 어 카인드 앤 찬스의 경우, 당신은 총 17개 이상인 5개의 주사위의 평균보다 더 나은 점수를 얻고자 한다.
풀 하우스와 스트레이트스의 경우, 일찍 낚시를 하고 실패한 시도를 당신의 상위 절반을 채우는 데 사용하세요.
진지한 플레이어의 경우, 최적으로 플레이하는 컴퓨터의 움직임과 비교할 수 있는 온라인 응용 프로그램이 있습니다(즉, 가능한 가장 많은 시나리오에서 전체적으로 가장 높은 점수를 받을 가능성이 높은 게임 만들기). 그것을 사용해 보고 여러분의 사고력을 향상시킬 수 있는지 보세요.
같은 웹사이트의 또 다른 앱은 당신이 야흐체의 전체 게임을 플레이하고 그 후에 모든 것을 분석할 수 있게 해준다. 다음은 분석을 읽는 방법에 대한 지침입니다.
야흐체즈 게임은 대상을 얻기 위해 유사한 주사위를 쫓는 것과 스트레이트를 쫓기 위해 중복된 주사위를 다시 굴리는 스트레이트 중 하나를 선택하도록 플레이어에게 도전한다. 야흐체를 얻는다는 것은 항상 스트레이트를 희생하면서 중복 주사위를 쫓아야 한다는 것을 의미한다. 이 '야흐체 1인자' 전략은 초기 롤에서 인사이드 스트레이트(4 다이, 2,3,4,5)를 얻을 때만 스트레이트를 쫓고, 그렇지 않으면 중복되지 않은 주사위를 다시 굴려 '야흐체'를 득점하도록 지시한다.
야흐체 변형 '얌스'는 몇 가지 변경 사항이 있는 대체 득점 시트를 도입한다. 예를 들어 '찬스', '3종', '리골'은 반대쪽 다이 페이스에서 4종 플러스 1종(6종 1개, 5종 2개, 4종 3개 등)을 떨어뜨린다.
f27de0f496cce3e57f63d63ca0e7d9faf5e43a7c
Gamehelpcheckers
0
241
1430
2023-01-10T09:55:05Z
Osizzoong
8648
새 문서: 체커/드래프트를 하는 방법에 대한 팁은 팁_체커를 참조하십시오 게임의 목표 '드래프트'로도 알려진 체커스는 거의 천 년 전으로 거슬러 올라가는 두 명의 플레이어를 위한 시대를 초월한 추상적인 전략 게임이다. 게임에서 당신은 상대편의 모든 조각을 뛰어넘어 보드에서 그것들을 제거할 때까지 당신의 조각들을 움직인다. 플레이어는 교대 플레이(빛으로 시작...
wikitext
text/x-wiki
체커/드래프트를 하는 방법에 대한 팁은 팁_체커를 참조하십시오
게임의 목표
'드래프트'로도 알려진 체커스는 거의 천 년 전으로 거슬러 올라가는 두 명의 플레이어를 위한 시대를 초월한 추상적인 전략 게임이다. 게임에서 당신은 상대편의 모든 조각을 뛰어넘어 보드에서 그것들을 제거할 때까지 당신의 조각들을 움직인다. 플레이어는 교대 플레이(빛으로 시작)에서 한 번에 한 조각씩 대각선으로 움직입니다. 사각형에 대한 모든 참조는 어두운 사각형만 참조합니다. 보드는 밝은 색과 어두운 색이 번갈아 나타나는 8x8 정사각형이다. 플레이어는 자신에게 가장 가까운 처음 세 줄의 12개의 어두운 사각형에 조각을 설치해야 한다(게임에서 라이트 스페이스는 완전히 무시된다).
게임 변형
체커의 변형이 많다. 보드 게임 아레나에서 이용할 수 있는 것은 다음과 같다:
국제 체커스 (10x10 보드, 남자는 뒤로 잡을 수 있고, 왕은 날 수 있으며, 가능한 한 많은 조각을 잡아야 한다.)
스트레이트 체커스 (8x8 보드, 남자는 뒤로 잡을 수 없고, 왕은 뒤로 잡을 수 있지만 날 수 없으며, 가능하면 많은 조각을 잡아야 하지만 반드시 많은 조각을 잡을 필요는 없다.)
브라질 체커스 (8x8 보드, 남자는 뒤로 잡을 수 있고, 왕은 날 수 있으며, 가능한 한 많은 조각을 잡아야 한다.)
러시아 체커(8x8 보드, 남자는 뒤로 잡을 수 있고, 왕은 왕관을 쓴 직후 날아서 계속해서 잡을 수 있으며, 가능하면 많은 조각을 잡을 필요는 없다.).
현재 플레이 중인 변형 모델의 규칙을 확인하십시오. 다음 세부 섹션은 스트레이트 체커에만 적용됩니다.
직선 체커
이동 및 캡처
각 플레이어의 체커가 없는 사각형에서 체커를 보드의 상대편을 향해 대각선으로 한 칸 앞으로 이동합니다. 체커가 상대 체커 뒤로 최대 한 공간에 위치한 경우 캡처 동작을 통해 상대 체커를 '점프'할 수 있습니다. 캡처할 때 두 개의 공간을 같은 방향으로 이동하는 체커를 뛰어넘은 다음 게임에서 그들의 조각을 제거합니다. 같은 턴에서 여러 개의 점프를 사용하여 여러 개의 피스를 캡처하는 것이 게임의 핵심 부분이며, 그렇게 할 때 대각선으로 움직이는 방향을 변경할 수 있지만 항상 앞으로 이동해야 합니다.
상대의 체커를 뛰어넘을 기회가 있다면 반드시 해야 한다.
더 이상 캡처할 수 없을 때까지 후속 체커 캡처를 계속할 수 있습니다.
상대 체커를 선택할 수 있는 기회가 있을 경우, 선택할 수 있지만 그 중 하나를 캡처해야 합니다.
8445d7c570d35a868c513ddfd2fbb26e139ebf1c
Tips catan
0
242
1431
2023-02-14T05:55:27Z
Hallykim
8744
새 문서: 첫번째턴에 마을을 짓는 장소는 결정적입니다. 중간 숫자인 5,6,8,9 중 많은 자원을 얻을 수 있는 곳이나 같은 자원을 얻을 수 있는 곳에 정착을 하여 필요한 자원을 효과적으로 거래 / 해상 거래할 수 있도록 해야 합니다. 그러나 도적(고무도둑)에 대해 조심해야 합니다. 만약 이게 당신의 칸 위에 있으면 아무것도 벌 수 없습니다! 항구: 초기 정착 중 하나를 항구...
wikitext
text/x-wiki
첫번째턴에 마을을 짓는 장소는 결정적입니다.
중간 숫자인 5,6,8,9 중 많은 자원을 얻을 수 있는 곳이나 같은 자원을 얻을 수 있는 곳에 정착을 하여 필요한 자원을 효과적으로 거래 / 해상 거래할 수 있도록 해야 합니다.
그러나 도적(고무도둑)에 대해 조심해야 합니다.
만약 이게 당신의 칸 위에 있으면 아무것도 벌 수 없습니다!
항구: 초기 정착 중 하나를 항구에 놓는 것은 유리할 수 있습니다. 그것은 거래를 바로 시작할 수 있게 해주기 때문입니다. 그러나 그 항구가 두 개의 칸 사이에 놓이도록 하고, 그 두 칸의 숫자가 일반적으로 강한 숫자 중 하나 (5,6,8,9)라면 그렇게 해야합니다. 또한, 두 번째 시작 정착지가 항구 위에 놓이는 경우, 시작 자원은 두 개만 받을 수 있습니다. 또한, 선택한 항구가 두 번째 시작 정착지의 위치와 함께 호환되도록해야합니다(예 : 첫 번째 정착지가 나무 항구에 놓이고, 첫 번째 또는 두 번째 정착지 중 하나 이상이 하나 이상의 나무 칸 위에 놓이는 경우).
1c1d789f8444aeb9471bb34afb236a4dee6b1ae7
Gamehelpwingspan
0
243
1432
2023-02-18T08:59:39Z
Goatenderloin
8753
새 문서: 게임 이전 플레이어들은 각자 5장의 새 카드, 종류별 먹이 하나씩(5가지가 있습니다), 보너스 목표 카드 두 장을 가지고 시작합니다--다음 지시사항에 따라 남길 것들을 선택합니다: 남길 카드 선택하기 우선 플레이어들은 각자 손에 남길 새 카드를 선택합니다. 그 다음, 손에 남긴 새 카드의 수만큼의 먹이를 버려야 합니다. (즉 플레이어는 새 카드를 많이 남길 수...
wikitext
text/x-wiki
게임 이전
플레이어들은 각자 5장의 새 카드, 종류별 먹이 하나씩(5가지가 있습니다), 보너스 목표 카드 두 장을 가지고 시작합니다--다음 지시사항에 따라 남길 것들을 선택합니다:
남길 카드 선택하기
우선 플레이어들은 각자 손에 남길 새 카드를 선택합니다.
그 다음, 손에 남긴 새 카드의 수만큼의 먹이를 버려야 합니다. (즉 플레이어는 새 카드를 많이 남길 수록 게임 시작에 더 적은 먹이를 가지고 있게 됩니다.)
마지막으로 플레이어들은 각자 게임동안 사용할 보너스 목표 카드 한 장을 선택합니다.
게임하기
턴 행동
플레이어의 턴에 다음 행동들 중 하나를 할 수 있습니다:
먹이 얻기: 모이통에서 선택 가능한 추가 먹이 얻기;
알 낳기: 알을 모으고 분배하기;
새 카드 뽑기: 선택 가능한 세 개의 카드 중 하나를 고르기; 또는
먹이를 지불하고 새 카드를 적절한 서식지에 두기
서식지와 새 능력 활성화
플레이어가 새를 놓기로 결정했다면, 어떤 새들은 추후에 서식지 행동을 할 때 활성화할 수 있는 갈색 능력을 가지고 있습니다. 새 카드를 놓는 것이 해당 새의 능력이나 그 서식지의 다른 새들의 능력을 활성화할 수 있는 것이 아님을 알아 두세요.
같은 서식지에 여러 새 카드를 놓게 되면 이미 다른 새에 놓인 알을 점점 많이 지불해야 합니다.
행동과 라운드
윙스팬은 총 4라운드로 진행됩니다. 각 라운드는 모든 플레이어들이 모든 행동을 마쳤을 때 끝납니다. 라운드가 진행 될수록 행동 횟수는 적어집니다.
점수와 목표
가장 많은 점수를 모으는 것이 목표입니다.
라운드 목표
각 라운드는 특정 기준을 충족시킬 시 점수를 주는 각각의 목표가 있습니다.(목표는 왼쪽 네모에 있습니다) 점수는 각 플레이어들의 순위에 따라 차등적으로 주어집니다.
게임 종료
플레이어들은 다음에 따라 점수를 얻습니다:
게임판에 놓인 새 카드 점수 합산;
새 카드 아래 '놓인' 다른 새 카드당 1점;
새 카드에 '저장'된 먹이 토큰 당 1점;
새 카드에 놓인 알의 합; 그리고
달성한 보너스 목표 카드
eddb4ef7dcf7cab9612a96962edefecf5e092c20
1433
1432
2023-02-18T09:01:45Z
Goatenderloin
8753
wikitext
text/x-wiki
게임 이전
플레이어들은 각자 5장의 새 카드, 종류별 먹이 하나씩(5가지가 있습니다), 보너스 목표 카드 두 장을 가지고 시작합니다--다음 지시사항에 따라 남길 것들을 선택합니다:
남길 카드 선택하기
우선 플레이어들은 각자 손에 남길 새 카드를 선택합니다.
그 다음, 손에 남긴 새 카드의 수만큼의 먹이를 버려야 합니다. (즉 플레이어는 새 카드를 많이 남길 수록 게임 시작에 더 적은 먹이를 가지고 있게 됩니다.)
마지막으로 플레이어들은 각자 게임동안 사용할 보너스 목표 카드 한 장을 선택합니다.
게임하기
턴 행동
플레이어의 턴에 다음 행동들 중 하나를 할 수 있습니다:
먹이 얻기: 모이통에서 선택 가능한 추가 먹이 얻기;
알 낳기: 알을 모으고 분배하기;
새 카드 뽑기: 선택 가능한 세 개의 카드 중 하나를 고르기; 또는
먹이를 지불하고 새 카드를 적절한 서식지에 두기
서식지와 새 능력 활성화
플레이어가 새를 놓기로 결정했다면, 어떤 새들은 추후에 서식지 행동을 할 때 활성화할 수 있는 갈색 능력을 가지고 있습니다. 새 카드를 놓는 것이 해당 새의 능력이나 그 서식지의 다른 새들의 능력을 활성화할 수 있는 것이 아님을 알아 두세요.
같은 서식지에 여러 새 카드를 놓게 되면 이미 다른 새에 놓인 알을 점점 많이 지불해야 합니다.
행동과 라운드
윙스팬은 총 4라운드로 진행됩니다. 각 라운드는 모든 플레이어들이 모든 행동을 마쳤을 때 끝납니다. 라운드가 진행 될수록 행동 횟수는 적어집니다.
점수와 목표
가장 많은 점수를 모으는 것이 목표입니다.
라운드 목표
각 라운드는 특정 기준을 충족시킬 시 점수를 주는 각각의 목표가 있습니다.(목표는 왼쪽 네모에 있습니다) 점수는 각 플레이어들의 순위에 따라 차등적으로 주어집니다.
게임 종료
플레이어들은 다음에 따라 점수를 얻습니다:
게임판에 놓인 새 카드 점수 합산;
새 카드 아래 '놓인' 다른 새 카드당 1점;
새 카드에 '저장'된 먹이 토큰 당 1점;
새 카드에 놓인 알의 합; 그리고
달성한 보너스 목표 카드
7978e24e610cbdfaf7a2dab7ea2c50bc02eac6c8
Gamehelpbang
0
199
1434
1304
2023-02-22T03:21:16Z
Pauljs123
8762
wikitext
text/x-wiki
직업
보안관, 부관, 무법자, 배신자 4개의 직업이 있으며 보안관은 직업을 공개한 채로 시작합니다. 이때 플레이어의 수에 따라
4명 : 1보안관, 2무법자, 1배신자
5명 : 1보안관, 2무법자, 1부관, 1배신자
6명 : 1보안관, 3무법자, 1부관, 1배신자
7명 : 1보안관, 3무법자, 2부관, 1배신자
로 게임이 진행됩니다.
승리조건
보안관, 부관 : 무법자와 배신자를 모두 처치하면 승리
무법자 : 보안관을 처치하면 승리
배신자 : 홀로 살아남으면 승리 (단, 무법자 혹은 부관이 생존했을때 보안관이 죽으면 무법자의 승리)
게임 시작
게임은 보안관부터 시작합니다.(카드 2장을 뽑기 전에 생명력만큼 카드를 듭니다.)
자신의 차례가 시작될 때 카드를 2장 뽑습니다. 이후 카드를 원하는 만큼 사용합니다. (단, 뱅! 은 한 턴에 한번만 사용할 수 있습니다)
차례를 마칠 때, 자신의 생명력 만큼 카드를 들고 있을 수 있으며 이외의 카드들은 버려야 합니다.
6ee17b1f1aaabb8c452ef327610489b864a1a906
1435
1434
2023-02-22T03:22:50Z
Pauljs123
8762
wikitext
text/x-wiki
직업
보안관, 부관, 무법자, 배신자 4개의 직업이 있으며 보안관은 직업을 공개한 채로 시작합니다. 이때 플레이어의 수에 따라
4명 : 1보안관, 2무법자, 1배신자
5명 : 1보안관, 2무법자, 1부관, 1배신자
6명 : 1보안관, 3무법자, 1부관, 1배신자
7명 : 1보안관, 3무법자, 2부관, 1배신자
로 게임이 진행됩니다.
승리조건
보안관, 부관 : 무법자와 배신자를 모두 처치하면 승리
무법자 : 보안관을 처치하면 승리
배신자 : 홀로 살아남으면 승리 (단, 무법자 혹은 부관이 생존했을때 보안관이 죽으면 무법자의 승리)
게임 시작
게임은 보안관부터 시작합니다.(카드 2장을 뽑기 전에 생명력만큼 카드를 가져옵니다.)
자신의 차례가 시작될 때 카드를 2장 뽑습니다. 이후 카드를 원하는 만큼 사용합니다. (단, 뱅! 은 한 턴에 한번만 사용할 수 있습니다)
차례를 마칠 때, 자신의 생명력 만큼 카드를 들고 있을 수 있으며 이외의 카드들은 버려야 합니다.
5f4f742d9ef2451f15e3745ebc9aca864d4a15f7
1436
1435
2023-02-22T03:27:10Z
Pauljs123
8762
wikitext
text/x-wiki
역할
보안관, 부관, 무법자, 배신자 4개의 직업이 있으며 보안관은 직업을 공개한 채로 시작합니다. 이때 플레이어의 수에 따라
4명 : 1보안관, 2무법자, 1배신자
5명 : 1보안관, 2무법자, 1부관, 1배신자
6명 : 1보안관, 3무법자, 1부관, 1배신자
7명 : 1보안관, 3무법자, 2부관, 1배신자
로 게임이 진행됩니다.
승리조건
보안관 : 무법자와 배신자를 모두 처치하면 승리
부 관 : 보완관을 지키면 승리
무법자 : 보안관을 처치하면 승리
배신자 : 홀로 살아남으면 승리 (단, 무법자 혹은 부관이 생존했을때 보안관이 죽으면 무법자의 승리)
게임 시작
게임은 보안관부터 시작합니다.(카드 2장을 뽑기 전에 생명력만큼 카드를 가져옵니다.)
자신의 차례가 시작될 때 카드를 2장 뽑습니다. 이후 카드를 원하는 만큼 사용합니다. (단, 뱅! 은 한 턴에 한번만 사용할 수 있습니다)
차례를 마칠 때, 자신의 생명력 만큼 카드를 들고 있을 수 있으며 이외의 카드들은 버려야 합니다.
749b78795a2f59840a7f925cd2c61d37a9278007
Tips gizmos
0
244
1437
2023-03-08T09:55:48Z
Tomatocheeze
8790
새 문서: 기즈모는 자원 관리 엔진 구축 게임이므로 목표는 각 자원의 획득과 가치를 극대화하는 것입니다. 주로 초기 게임에서 에너지(그리고 간접적으로 엔진 동력)를 사용한 후 후반 게임에서 포인트를 제공합니다. 따라서 자연스럽게 당신은 더 많은 에너지와 더 많은 포인트를 얻을 수 있도록 돕는 기즈모에 집중해야 합니다. 처음에는 한 번에 하나의 작업을 수행하는...
wikitext
text/x-wiki
기즈모는 자원 관리 엔진 구축 게임이므로 목표는 각 자원의 획득과 가치를 극대화하는 것입니다. 주로 초기 게임에서 에너지(그리고 간접적으로 엔진 동력)를 사용한 후 후반 게임에서 포인트를 제공합니다. 따라서 자연스럽게 당신은 더 많은 에너지와 더 많은 포인트를 얻을 수 있도록 돕는 기즈모에 집중해야 합니다.
처음에는 한 번에 하나의 작업을 수행하는 것으로 제한됩니다. 당신의 목표는 가능한 한 빨리 추가 조치를 취하는 것입니다. 이 시점에서 업그레이드 기즈모를 구입하는 것은 일반적으로 매우 좋지 않은 생각입니다. 컨버터를 구입하는 것도 좋지만, 대부분의 경우 빌드 시 뽑기 기즈모 > 픽 시 뽑기 기즈모 > 파일 시 픽 기즈모를 찾아야 합니다. 이 중 하나 이상이 있으면 색상과 일치하는 다른 기즈모를 찾아야 합니다. 만약 당신이 이미 레드 빌드시 픽 기즈모를 가지고 있다면, 레드 빌드시 점수 토큰(VP) 기즈모를 사는 것은 환상적입니다. 이미 파란색 픽 시 뽑기 트리거가 있는 경우 파란색 컨버터를 구입하는 것이 좋습니다. 그렇긴 하지만, 만약 그것이 당신이 이용할 수 있는 유일한 옵션이라면, 다른 색에 관한것을 뽑는 것도 나쁘지 않습니다. 기즈모/에너지를 단색만 추구하지 않도록 유연하게 연출하는 것이 좋습니다.
당신의 첫 번째 행동은 거의 항상 기즈모를 파일하는 것이어야 합니다. I 또는 II 행에 빌드 또는 선택 트리거가 없는 경우 레벨 I을 조사하여 트리거를 찾습니다.
6b2888f8444b7760e41d7eafce2d96e07b0ebef8
1438
1437
2023-03-08T10:38:11Z
Tomatocheeze
8790
wikitext
text/x-wiki
기즈모는 자원 관리 엔진 구축 게임이므로 목표는 각 자원의 획득과 가치를 극대화하는 것입니다. 주로 초기 게임에서 에너지(그리고 간접적으로 엔진 동력)를 사용한 후 후반 게임에서 포인트를 제공합니다. 따라서 자연스럽게 당신은 더 많은 에너지와 더 많은 포인트를 얻을 수 있도록 돕는 기즈모에 집중해야 합니다.
처음에는 한 번에 하나의 작업을 수행하는 것으로 제한됩니다. 당신의 목표는 가능한 한 빨리 추가 조치를 취하는 것입니다. 이 시점에서 업그레이드 기즈모를 구입하는 것은 일반적으로 매우 좋지 않은 생각입니다. 컨버터를 구입하는 것도 좋지만, 대부분의 경우 제작 시 뽑기 기즈모 > 획득 시 뽑기 기즈모 > 수집 시 획득 기즈모를 찾아야 합니다. 이 중 하나 이상이 있으면 색상과 일치하는 다른 기즈모를 찾아야 합니다. 만약 당신이 이미 빨강 제작 시 획득 기즈모를 가지고 있다면, 빨강 제작시 점수 토큰 기즈모를 사는 것은 환상적입니다. 이미 파란색 획득 시 뽑기 기즈모가 있는 경우 파란색 변환 기즈모를 구입하는 것이 좋습니다. 그렇긴 하지만, 만약 그것이 당신이 이용할 수 있는 유일한 옵션이라면, 다른 색에 관한것을 뽑는 것도 나쁘지 않습니다. 기즈모/에너지를 단색만 추구하지 않도록 유연하게 연출하는 것이 좋습니다.
당신의 첫 번째 행동은 거의 항상 기즈모를 수집하는 것이어야 합니다. I 또는 II 행에 빌드 또는 선택 트리거가 없는 경우 레벨 I을 조사하여 트리거를 찾습니다.
수집 전략
어떤 사람들은 기즈모에 두 가지 전략이 있다고 믿는다는 것을 언급할 가치가 있습니다. 하나는 많이 제작 하는 것에 초점을 맞춘 전략이고 다른 하나는 많이 수집하는 것에 초점을 맞춘 전략입니다. 많은 기즈모를 구축하는 것이 수집 전략 보다 훨씬 더 빨리 게임을 끝내기 때문에 잘 실행된 제작 전략은 90% 이상의 경우 수집 중심 전략을 능가할 것입니다. 모든 수집을 하면 제작할 수 있는 기회가 하나 줄어듭니다. 수집 전략이 가질 수 있는 유일한 기회는 레벨 III 기즈모를 4개를 구축하는 것이지만 이는 거의 통합되지 않습니다. 상대를 탬포에 맞추는 것은 매우 중요합니다.
좋은 제작/획득 엔진을 사용할 경우 업그레이드, 제작시 점수토큰 및 변환 기즈모 구매 가치가 높아집니다.
기즈모에서 가장 기술적인 부분은 연구를 통해 잠재적으로 최적화되지 않은 기즈모를 받아들이는 위험을 감수해야 하는 시기를 결정하는 것입니다. 이것은 단순히 시간이 지남에 따라 직관을 구축해야 하는 것이지만, 무작위성을 완화하는 것과 관련된 모든 게임에 존재하는 일반적인 원칙을 언급할 가치가 있습니다: 얼마나 위험한지는 얼마나 이기고 있는지와 반비례해야 합니다. 이기고 있어요? 불필요한 위험을 감수하지 말고 계속해서 이기세요. 지고 있나요? 큰 위험을 감수하세요. 그렇지 않으면 질 것입니다. 분명히 당신은 보통 그 사이에 있지만 원칙은 중요합니다.
레벨 3 멀티 컬러 기즈모는 모든 빌드 카드를 트리거합니다. 이러한 이유로 점수토큰 기즈모가 일반적인 제작 색상과 일치하지 않더라도 제작하는 것이 좋습니다. 또한 각 게임에는 36개의 풀 중 16개의 레벨 III 카드가 랜덤으로 포함되어 있습니다. 따라서 가능성은 낮지만, 다양한 색상의 기즈모 중 어느 것도 게임에 등장하지 못하는 것은 전적으로 가능합니다. 전체를 조사하기 전에는 알 방법이 없습니다.
당신이 상대적으로 어느 지점에 있는지 재평가하세요. 마무리 투수를 찾으려면 레벨 III를 조사해야 합니까? 아니면 그냥 레벨 2를 올려서 승리를 거둘 수 있나요? 16 기즈모를 만드는 사람이 대부분 승자입니다. 첫 번째 플레이어가 누구인지 다시 확인하여 누가 턴을 받을지 알 수 있습니다. 경기의 속도를 조절하는 선수가 되도록 노력하세요.
7e8571626254102450f930347862228c14a009c5
1439
1438
2023-03-08T10:40:25Z
Tomatocheeze
8790
wikitext
text/x-wiki
기즈모는 자원 관리 엔진 구축 게임이므로 목표는 각 자원의 획득과 가치를 극대화하는 것입니다. 주로 초기 게임에서 에너지(그리고 간접적으로 엔진 동력)를 사용한 후 후반 게임에서 포인트를 제공합니다. 따라서 자연스럽게 당신은 더 많은 에너지와 더 많은 포인트를 얻을 수 있도록 돕는 기즈모에 집중해야 합니다.
== 게임 초반 ==
처음에는 한 번에 하나의 작업을 수행하는 것으로 제한됩니다. 당신의 목표는 가능한 한 빨리 추가 조치를 취하는 것입니다. 이 시점에서 업그레이드 기즈모를 구입하는 것은 일반적으로 매우 좋지 않은 생각입니다. 컨버터를 구입하는 것도 좋지만, 대부분의 경우 제작 시 뽑기 기즈모 > 획득 시 뽑기 기즈모 > 수집 시 획득 기즈모를 찾아야 합니다. 이 중 하나 이상이 있으면 색상과 일치하는 다른 기즈모를 찾아야 합니다. 만약 당신이 이미 빨강 제작 시 획득 기즈모를 가지고 있다면, 빨강 제작시 점수 토큰 기즈모를 사는 것은 환상적입니다. 이미 파란색 획득 시 뽑기 기즈모가 있는 경우 파란색 변환 기즈모를 구입하는 것이 좋습니다. 그렇긴 하지만, 만약 그것이 당신이 이용할 수 있는 유일한 옵션이라면, 다른 색에 관한것을 뽑는 것도 나쁘지 않습니다. 기즈모/에너지를 단색만 추구하지 않도록 유연하게 연출하는 것이 좋습니다.
당신의 첫 번째 행동은 거의 항상 기즈모를 수집하는 것이어야 합니다. I 또는 II 행에 빌드 또는 선택 트리거가 없는 경우 레벨 I을 조사하여 트리거를 찾습니다.
===수집 전략===
어떤 사람들은 기즈모에 두 가지 전략이 있다고 믿는다는 것을 언급할 가치가 있습니다. 하나는 많이 제작 하는 것에 초점을 맞춘 전략이고 다른 하나는 많이 수집하는 것에 초점을 맞춘 전략입니다. 많은 기즈모를 구축하는 것이 수집 전략 보다 훨씬 더 빨리 게임을 끝내기 때문에 잘 실행된 제작 전략은 90% 이상의 경우 수집 중심 전략을 능가할 것입니다. 모든 수집을 하면 제작할 수 있는 기회가 하나 줄어듭니다. 수집 전략이 가질 수 있는 유일한 기회는 레벨 III 기즈모를 4개를 구축하는 것이지만 이는 거의 통합되지 않습니다. 상대를 탬포에 맞추는 것은 매우 중요합니다.
== 게임 중반/ 일반적인 전략 ==
좋은 제작/획득 엔진을 사용할 경우 업그레이드, 제작시 점수토큰 및 변환 기즈모 구매 가치가 높아집니다.
기즈모에서 가장 기술적인 부분은 연구를 통해 잠재적으로 최적화되지 않은 기즈모를 받아들이는 위험을 감수해야 하는 시기를 결정하는 것입니다. 이것은 단순히 시간이 지남에 따라 직관을 구축해야 하는 것이지만, 무작위성을 완화하는 것과 관련된 모든 게임에 존재하는 일반적인 원칙을 언급할 가치가 있습니다: 얼마나 위험한지는 얼마나 이기고 있는지와 반비례해야 합니다. 이기고 있어요? 불필요한 위험을 감수하지 말고 계속해서 이기세요. 지고 있나요? 큰 위험을 감수하세요. 그렇지 않으면 질 것입니다. 분명히 당신은 보통 그 사이에 있지만 원칙은 중요합니다.
레벨 3 멀티 컬러 기즈모는 모든 빌드 카드를 트리거합니다. 이러한 이유로 점수토큰 기즈모가 일반적인 제작 색상과 일치하지 않더라도 제작하는 것이 좋습니다. 또한 각 게임에는 36개의 풀 중 16개의 레벨 III 카드가 랜덤으로 포함되어 있습니다. 따라서 가능성은 낮지만, 다양한 색상의 기즈모 중 어느 것도 게임에 등장하지 못하는 것은 전적으로 가능합니다. 전체를 조사하기 전에는 알 방법이 없습니다.
== 게임 후반 ==
당신이 상대적으로 어느 지점에 있는지 재평가하세요. 마무리 투수를 찾으려면 레벨 III를 조사해야 합니까? 아니면 그냥 레벨 2를 올려서 승리를 거둘 수 있나요? 16 기즈모를 만드는 사람이 대부분 승자입니다. 첫 번째 플레이어가 누구인지 다시 확인하여 누가 턴을 받을지 알 수 있습니다. 경기의 속도를 조절하는 선수가 되도록 노력하세요.
8a6cf4707689e962b696e2161c6add2b76561b33
1440
1439
2023-03-08T10:40:51Z
Tomatocheeze
8790
/* 게임 초반 */
wikitext
text/x-wiki
기즈모는 자원 관리 엔진 구축 게임이므로 목표는 각 자원의 획득과 가치를 극대화하는 것입니다. 주로 초기 게임에서 에너지(그리고 간접적으로 엔진 동력)를 사용한 후 후반 게임에서 포인트를 제공합니다. 따라서 자연스럽게 당신은 더 많은 에너지와 더 많은 포인트를 얻을 수 있도록 돕는 기즈모에 집중해야 합니다.
== 게임 초반 ==
처음에는 한 번에 하나의 작업을 수행하는 것으로 제한됩니다. 당신의 목표는 가능한 한 빨리 추가 조치를 취하는 것입니다. 이 시점에서 업그레이드 기즈모를 구입하는 것은 일반적으로 매우 좋지 않은 생각입니다. 컨버터를 구입하는 것도 좋지만, 대부분의 경우 제작 시 뽑기 기즈모 > 획득 시 뽑기 기즈모 > 수집 시 획득 기즈모를 찾아야 합니다. 이 중 하나 이상이 있으면 색상과 일치하는 다른 기즈모를 찾아야 합니다. 만약 당신이 이미 빨강 제작 시 획득 기즈모를 가지고 있다면, 빨강 제작시 점수 토큰 기즈모를 사는 것은 환상적입니다. 이미 파란색 획득 시 뽑기 기즈모가 있는 경우 파란색 변환 기즈모를 구입하는 것이 좋습니다. 그렇긴 하지만, 만약 그것이 당신이 이용할 수 있는 유일한 옵션이라면, 다른 색에 관한것을 뽑는 것도 나쁘지 않습니다. 기즈모/에너지를 단색만 추구하지 않도록 유연하게 연출하는 것이 좋습니다.
당신의 첫 번째 행동은 거의 항상 기즈모를 수집하는 것이어야 합니다. I 또는 II 행에 빌드 또는 선택 트리거가 없는 경우 레벨 I을 조사하여 트리거를 찾습니다.
===수집 전략===
어떤 사람들은 기즈모에 두 가지 전략이 있다고 믿는다는 것을 언급할 가치가 있습니다. 하나는 많이 제작 하는 것에 초점을 맞춘 전략이고 다른 하나는 많이 수집하는 것에 초점을 맞춘 전략입니다. 많은 기즈모를 구축하는 것이 수집 전략 보다 훨씬 더 빨리 게임을 끝내기 때문에 잘 실행된 제작 전략은 90% 이상의 경우 수집 중심 전략을 능가할 것입니다. 모든 수집을 하면 제작할 수 있는 기회가 하나 줄어듭니다. 수집 전략이 가질 수 있는 유일한 기회는 레벨 III 기즈모를 4개를 구축하는 것이지만 이는 거의 통합되지 않습니다. 상대를 탬포에 맞추는 것은 매우 중요합니다.
== 게임 중반/ 일반적인 전략 ==
좋은 제작/획득 엔진을 사용할 경우 업그레이드, 제작시 점수토큰 및 변환 기즈모 구매 가치가 높아집니다.
기즈모에서 가장 기술적인 부분은 연구를 통해 잠재적으로 최적화되지 않은 기즈모를 받아들이는 위험을 감수해야 하는 시기를 결정하는 것입니다. 이것은 단순히 시간이 지남에 따라 직관을 구축해야 하는 것이지만, 무작위성을 완화하는 것과 관련된 모든 게임에 존재하는 일반적인 원칙을 언급할 가치가 있습니다: 얼마나 위험한지는 얼마나 이기고 있는지와 반비례해야 합니다. 이기고 있어요? 불필요한 위험을 감수하지 말고 계속해서 이기세요. 지고 있나요? 큰 위험을 감수하세요. 그렇지 않으면 질 것입니다. 분명히 당신은 보통 그 사이에 있지만 원칙은 중요합니다.
레벨 3 멀티 컬러 기즈모는 모든 빌드 카드를 트리거합니다. 이러한 이유로 점수토큰 기즈모가 일반적인 제작 색상과 일치하지 않더라도 제작하는 것이 좋습니다. 또한 각 게임에는 36개의 풀 중 16개의 레벨 III 카드가 랜덤으로 포함되어 있습니다. 따라서 가능성은 낮지만, 다양한 색상의 기즈모 중 어느 것도 게임에 등장하지 못하는 것은 전적으로 가능합니다. 전체를 조사하기 전에는 알 방법이 없습니다.
== 게임 후반 ==
당신이 상대적으로 어느 지점에 있는지 재평가하세요. 마무리 투수를 찾으려면 레벨 III를 조사해야 합니까? 아니면 그냥 레벨 2를 올려서 승리를 거둘 수 있나요? 16 기즈모를 만드는 사람이 대부분 승자입니다. 첫 번째 플레이어가 누구인지 다시 확인하여 누가 턴을 받을지 알 수 있습니다. 경기의 속도를 조절하는 선수가 되도록 노력하세요.
3486b170378cc1f4526f26b677123fd45c9533f3
Gamehelpgizmos
0
245
1441
2023-03-08T12:25:52Z
Tomatocheeze
8790
새 문서: == 개요 == 기즈모는 엔진 빌딩 자원 관리 게임입니다. 여러분은 하나의 액션으로 구성된 간단한 턴부터 시작하여 엔진을 빌드업하여 한 턴에 많은 액션을 발동할 수 있는 지점까지 진행할 것입니다 플레이어의 차례입니다 다음 작업 중 하나를 수행해야 합니다: 수집: 디스플레이 영역에서 기즈모를 하나 수집합니다. 획득: 에너지 레일에서 선택한 에너지 1개를...
wikitext
text/x-wiki
== 개요 ==
기즈모는 엔진 빌딩 자원 관리 게임입니다. 여러분은 하나의 액션으로 구성된 간단한 턴부터 시작하여 엔진을 빌드업하여 한 턴에 많은 액션을 발동할 수 있는 지점까지 진행할 것입니다
플레이어의 차례입니다
다음 작업 중 하나를 수행해야 합니다:
수집: 디스플레이 영역에서 기즈모를 하나 수집합니다.
획득: 에너지 레일에서 선택한 에너지 1개를 획득합니다.
제작: 디스플레이 영역 또는 아카이브에서 1개의 기즈모를 빌드합니다.
연구: 3개의 레벨 덱 중 하나에서 기즈모 카드를 뽑고 수집 또는 제작할 1개를 선택합니다
==수집==
디스플레이 영역에서 1개의 기즈모 카드를 선택한 다음 수집을 선택합니다. 기즈모 수집 후 즉시 해당 덱의 상단 카드로 교체됩니다. 이 새 기즈모를 뽑으면 수집 작업이 종료됩니다.
플레이어 대시보드의 업그레이드 영역에 표시된 만큼 수집에는 수집할 수 있는 기즈모 수가 제한됩니다. 각 플레이어는 수집 제한을 1로 설정하고 게임을 시작하지만, 일부 업그레이드 기즈모는 이 수를 늘립니다. 보관 파일은 파일 제한보다 많은 크기를 보관할 수 없으므로, 제한에 도달하면 파일 작업을 수행할 수 없습니다.
==획득==
에너지 레일에 있는 6개 중 1개의 에너지를 선택하여 에너지 저장 링에 추가합니다. 플레이어 대시보드의 업그레이드 영역에 표시된 만큼 에너지 저장 링에 저장할 수 있는 에너지가 제한되어 있습니다. 각 플레이어는 저장 제한을 5로 설정하고 게임을 시작하지만 일부 압그레이드 기즈모는 이 수를 늘릴 것입니다. 링에는 에너지 저장 한도 이상의 에너지를 저장할 수 없으므로, 한계에 도달하면 기존의 에너지를 사용하지 않는 한 더 이상의 에너지를 수집할 수 없습니다.
중요: 일부 기능을 사용하면 임의 에너지를 뽑을 수 있습니다. 이 작업은 획득 작업이 아니므로 다른 작업을 트리거하지 않습니다.
==제작==
디스플레이 영역 또는 아카이브에서 1개의 기즈모 카드를 선택합니다. 기즈모의 에너지 유형과 비용에 맞는 에너지 저장 링의 에너지를 사용하십시오. 디스플레이 영역에서 기즈모를 만든 후 즉시 해당 덱 상단에서 새로운 기즈모로 교체됩니다. 보충 후 제작 작업이 종료됩니다.
제작한 기즈모는 플레이어 대시보드 아래로 이동하여 모든 효과를 볼 수 있습니다.
==변환==
제작 작업을 수행할 때 변환 기즈모를 사용하여 보유한 에너지를 필요한 에너지로 변환할 수 있습니다. 보유한 변환기를 선택하여 이 작업을 수행할 수 있습니다. 변환기 유형에 대한 자세한 내용은 링크된 효과 목록 PDF에서 확인할 수 있습니다.
==연구==.
레벨 덱(1, 2 또는 3)을 선택하고 연구량과 동일한 카드 수를 그립니다. 한 번에 두 개 이상의 레벨 덱에서 뽑을 수 없습니다. 각 플레이어는 연구량 3으로 게임을 시작하지만, 일부 업그레이드 기즈모는 그 수를 늘립니다. 선택한 레벨 덱의 카드 수가 연구량 보다 적을 경우 사용 가능한 카드 수만 뽑습니다. 카드를 뽑은 후 1개를 선택하고 제작(에너지가 충분한 경우) 또는 수집(Archive에 공간이 있는 경우)을 선택합니다. 또는 둘 다 수행하지 않고 통과하도록 선택할 수 있습니다.
그런 다음 나머지 카드는 선택한 순서대로 해당 레벨 덱의 맨 아래로 돌아갑니다.
참고: 연구 작업 중에 수행하는 파일 또는 빌드 작업도 기즈모를 트리거하는 데 카운트됩니다(아래 Gizmo 효과 트리거 참조).
==기즈모 효과를 트리거==
사용 가능한 4가지 액션 중 하나를 취하는 것이 게임의 기본이지만, 게임의 진정한 핵심(그리고 승리의 열쇠)은 당신의 차례에 훨씬 더 많은 것을 얻기 위해 당신의 기즈모의 효과를 발동시키는 것입니다. 플레이어 대시보드 아래에 제작하고 배치하는 모든 기즈모에는 특정 트리거에 의해 활성화되는 효과가 있습니다(이에 대한 자세한 내용은 효과 목록의 링크된 PDF 참조). 작업을 수행할 때마다 트리거된 기즈모가 강조 표시됩니다. 트리거 작업이 완료된 후 원하는 순서로 트리거된 기즈모의 효과를 활성화할 수 있습니다. 트리거 조건이 두 번 이상 충족되더라도 각 기즈모는 한 번에 한 번만 사용할 수 있습니다.
참고: 기즈모가 만들어진 턴에도 기즈모의 효과를 사용할 수 있습니다. 그러나 제작한 작업과 동일한 작업에 의해 트리거될 수 없습니다.
==연쇄 반응==
최고의 발명가들의 비밀은 하나의 기즈모가 다른 기즈모를 촉발시켜 많은 이익을 창출하는 연쇄 반응을 일으킬 방법으로 기즈모를 민드는 것입니다! 기즈모 하나의 효과는 원래 수행된 액션과 다른 액션일 수 있습니다. 그런 다음 보조 작업을 수행하면 다른 기즈모를 트리거할 수 있습니다. 작업을 수행할 때마다 해당 순서에 대한 하나의 작업이든, 기즈모 효과에 의해 트리거된 작업이든 상관없이 항상 해당 작업의 기즈모를 확인하여 트리거된 작업이 있는지 확인하십시오.
활성화할 수 있는 기즈모의 수에는 제한이 없지만, 각 기즈모는 한 번에 한 번만 사용할 수 있다는 것을 항상 기억하십시오.
각 Gizmo의 효과가 실행되는 순서는 효과가 발생한 순서에 관계없이 플레이어에게 달려 있습니다. 연쇄 반응의 처음에 만들어진 기즈모는 그것을 만든 행동에 의해 촉발되지 않는 한, 그 연쇄 반응의 나중에 활성화될 수 있습니다. 때로는 작업과 효과를 실행하기 위한 최적의 순서를 찾는 것이 더 큰 결과를 얻을 수 있습니다.
==게임의 끝==
게임의 끝은 플레이어가 4번째 레벨 3 기즈모 또는 16번째 기즈모(시작 기즈모 포함)를 제작할 때 입니다. 그러면 첫 번째 플레이어의 오른쪽에 있는 플레이어가 차례를 마칠 때까지 게임이 계속됩니다. 즉, 모든 플레이어가 게임에서 동일한 턴 수를 가질 때까지입니다. 게임 종료를 트리거한 플레이어가 첫 번째 플레이어의 오른쪽에 있는 플레이어일 경우, 차례가 끝나면 게임이 종료됩니다.
당연히 승리 포인트가 가장 많은 선수가 승리합니다! 동점일 경우, 액티브 기즈모 영역에서 가장 많은 기즈모를 가진 동점자가 승리합니다(필드 기즈모는 포함되지 않음). 여전히 동점일 경우, 에너지 저장 링에 가장 많은 에너지가 남아 있는 동점자가 승리합니다. 그래도 동점일 경우 첫 번째 플레이어에서 가장 멀리 있는 동점자가 승리합니다.
c7d1ec0804289d07e49cf7c18665c3354c821e1f
1442
1441
2023-03-08T12:26:18Z
Tomatocheeze
8790
/* 기즈모 효과를 트리거 */
wikitext
text/x-wiki
== 개요 ==
기즈모는 엔진 빌딩 자원 관리 게임입니다. 여러분은 하나의 액션으로 구성된 간단한 턴부터 시작하여 엔진을 빌드업하여 한 턴에 많은 액션을 발동할 수 있는 지점까지 진행할 것입니다
플레이어의 차례입니다
다음 작업 중 하나를 수행해야 합니다:
수집: 디스플레이 영역에서 기즈모를 하나 수집합니다.
획득: 에너지 레일에서 선택한 에너지 1개를 획득합니다.
제작: 디스플레이 영역 또는 아카이브에서 1개의 기즈모를 빌드합니다.
연구: 3개의 레벨 덱 중 하나에서 기즈모 카드를 뽑고 수집 또는 제작할 1개를 선택합니다
==수집==
디스플레이 영역에서 1개의 기즈모 카드를 선택한 다음 수집을 선택합니다. 기즈모 수집 후 즉시 해당 덱의 상단 카드로 교체됩니다. 이 새 기즈모를 뽑으면 수집 작업이 종료됩니다.
플레이어 대시보드의 업그레이드 영역에 표시된 만큼 수집에는 수집할 수 있는 기즈모 수가 제한됩니다. 각 플레이어는 수집 제한을 1로 설정하고 게임을 시작하지만, 일부 업그레이드 기즈모는 이 수를 늘립니다. 보관 파일은 파일 제한보다 많은 크기를 보관할 수 없으므로, 제한에 도달하면 파일 작업을 수행할 수 없습니다.
==획득==
에너지 레일에 있는 6개 중 1개의 에너지를 선택하여 에너지 저장 링에 추가합니다. 플레이어 대시보드의 업그레이드 영역에 표시된 만큼 에너지 저장 링에 저장할 수 있는 에너지가 제한되어 있습니다. 각 플레이어는 저장 제한을 5로 설정하고 게임을 시작하지만 일부 압그레이드 기즈모는 이 수를 늘릴 것입니다. 링에는 에너지 저장 한도 이상의 에너지를 저장할 수 없으므로, 한계에 도달하면 기존의 에너지를 사용하지 않는 한 더 이상의 에너지를 수집할 수 없습니다.
중요: 일부 기능을 사용하면 임의 에너지를 뽑을 수 있습니다. 이 작업은 획득 작업이 아니므로 다른 작업을 트리거하지 않습니다.
==제작==
디스플레이 영역 또는 아카이브에서 1개의 기즈모 카드를 선택합니다. 기즈모의 에너지 유형과 비용에 맞는 에너지 저장 링의 에너지를 사용하십시오. 디스플레이 영역에서 기즈모를 만든 후 즉시 해당 덱 상단에서 새로운 기즈모로 교체됩니다. 보충 후 제작 작업이 종료됩니다.
제작한 기즈모는 플레이어 대시보드 아래로 이동하여 모든 효과를 볼 수 있습니다.
==변환==
제작 작업을 수행할 때 변환 기즈모를 사용하여 보유한 에너지를 필요한 에너지로 변환할 수 있습니다. 보유한 변환기를 선택하여 이 작업을 수행할 수 있습니다. 변환기 유형에 대한 자세한 내용은 링크된 효과 목록 PDF에서 확인할 수 있습니다.
==연구==.
레벨 덱(1, 2 또는 3)을 선택하고 연구량과 동일한 카드 수를 그립니다. 한 번에 두 개 이상의 레벨 덱에서 뽑을 수 없습니다. 각 플레이어는 연구량 3으로 게임을 시작하지만, 일부 업그레이드 기즈모는 그 수를 늘립니다. 선택한 레벨 덱의 카드 수가 연구량 보다 적을 경우 사용 가능한 카드 수만 뽑습니다. 카드를 뽑은 후 1개를 선택하고 제작(에너지가 충분한 경우) 또는 수집(Archive에 공간이 있는 경우)을 선택합니다. 또는 둘 다 수행하지 않고 통과하도록 선택할 수 있습니다.
그런 다음 나머지 카드는 선택한 순서대로 해당 레벨 덱의 맨 아래로 돌아갑니다.
참고: 연구 작업 중에 수행하는 파일 또는 빌드 작업도 기즈모를 트리거하는 데 카운트됩니다(아래 Gizmo 효과 트리거 참조).
==기즈모 효과 트리거==
사용 가능한 4가지 액션 중 하나를 취하는 것이 게임의 기본이지만, 게임의 진정한 핵심(그리고 승리의 열쇠)은 당신의 차례에 훨씬 더 많은 것을 얻기 위해 당신의 기즈모의 효과를 발동시키는 것입니다. 플레이어 대시보드 아래에 제작하고 배치하는 모든 기즈모에는 특정 트리거에 의해 활성화되는 효과가 있습니다(이에 대한 자세한 내용은 효과 목록의 링크된 PDF 참조). 작업을 수행할 때마다 트리거된 기즈모가 강조 표시됩니다. 트리거 작업이 완료된 후 원하는 순서로 트리거된 기즈모의 효과를 활성화할 수 있습니다. 트리거 조건이 두 번 이상 충족되더라도 각 기즈모는 한 번에 한 번만 사용할 수 있습니다.
참고: 기즈모가 만들어진 턴에도 기즈모의 효과를 사용할 수 있습니다. 그러나 제작한 작업과 동일한 작업에 의해 트리거될 수 없습니다.
==연쇄 반응==
최고의 발명가들의 비밀은 하나의 기즈모가 다른 기즈모를 촉발시켜 많은 이익을 창출하는 연쇄 반응을 일으킬 방법으로 기즈모를 민드는 것입니다! 기즈모 하나의 효과는 원래 수행된 액션과 다른 액션일 수 있습니다. 그런 다음 보조 작업을 수행하면 다른 기즈모를 트리거할 수 있습니다. 작업을 수행할 때마다 해당 순서에 대한 하나의 작업이든, 기즈모 효과에 의해 트리거된 작업이든 상관없이 항상 해당 작업의 기즈모를 확인하여 트리거된 작업이 있는지 확인하십시오.
활성화할 수 있는 기즈모의 수에는 제한이 없지만, 각 기즈모는 한 번에 한 번만 사용할 수 있다는 것을 항상 기억하십시오.
각 Gizmo의 효과가 실행되는 순서는 효과가 발생한 순서에 관계없이 플레이어에게 달려 있습니다. 연쇄 반응의 처음에 만들어진 기즈모는 그것을 만든 행동에 의해 촉발되지 않는 한, 그 연쇄 반응의 나중에 활성화될 수 있습니다. 때로는 작업과 효과를 실행하기 위한 최적의 순서를 찾는 것이 더 큰 결과를 얻을 수 있습니다.
==게임의 끝==
게임의 끝은 플레이어가 4번째 레벨 3 기즈모 또는 16번째 기즈모(시작 기즈모 포함)를 제작할 때 입니다. 그러면 첫 번째 플레이어의 오른쪽에 있는 플레이어가 차례를 마칠 때까지 게임이 계속됩니다. 즉, 모든 플레이어가 게임에서 동일한 턴 수를 가질 때까지입니다. 게임 종료를 트리거한 플레이어가 첫 번째 플레이어의 오른쪽에 있는 플레이어일 경우, 차례가 끝나면 게임이 종료됩니다.
당연히 승리 포인트가 가장 많은 선수가 승리합니다! 동점일 경우, 액티브 기즈모 영역에서 가장 많은 기즈모를 가진 동점자가 승리합니다(필드 기즈모는 포함되지 않음). 여전히 동점일 경우, 에너지 저장 링에 가장 많은 에너지가 남아 있는 동점자가 승리합니다. 그래도 동점일 경우 첫 번째 플레이어에서 가장 멀리 있는 동점자가 승리합니다.
62d6e44f6dcb149ba2621c8a153cbca1479de405
Gamehelpabandonallartichokes
0
198
1443
1308
2023-03-14T04:18:30Z
Ciwlx
8802
wikitext
text/x-wiki
==아티초크 버리기==
으악! 밭에 아티초크가 잔뜩 (10장이나!) 자라났습니다. 정원에서 자라는 채소를 사용하여 아티초크를 모두 퇴비로 만들어주세요.
손에서 아티초크를 모두 없앤 플레이어가 승리합니다.
==게임 진행==
아티초크를 제외한 채소 카드를 모두 섞어 정원 카드 더미를 만들어 뒷면으로 놓고, 5장을 뽑아 정원을 구성합니다.
플레이어마다 아티초크를 10장씩 받아 카드 더미에 뒷면으로 놓은 다음, 5장을 뽑아 손에 듭니다.
이제 가장 최근에 녹색 채소 요리를 먹은 사람이 맨 먼저 차례를 시작합니다.
자신의 턴에는 다음의 다섯 단계를 순서대로 진행합니다.
#정원의 카드가 5장 미만이라면 정원 카드 더미에서 부족한 만큼 뽑아 5장을 채웁니다.
#정원에서 채소 카드 하나를 선택해 손으로 가져옵니다.
# 손에 있는 채소 카드를 원하는 만큼 사용합니다. 카드의 효과를 모두 충족할 수 있을때만 카드를 사용할 수 있습니다 (예: 손에 아티초크가 1장뿐이라면 당근을 사용하여 1장만 묻을 수는 없습니다.)
#카드 사용이 끝나면 손에 남은 카드를 모두 버립니다.
#내 카드 더미에서 카드를 5장 뽑습니다. 카드 더미에 카드가 부족하다면 버린 카드 더미를 섞어 카드 더미로 사용합니다.
마지막 단계에서 카드를 5장 뽑았을 때 손에 아티초크가 한 장도 없다면 게임에서 승리합니다! 자신의 턴 중간이나 상대의 턴에는 손에 아티초크가 없는 상태라도 승리하지 않습니다.
==카드 설명==
아티초크는 플레이어마다 10장씩 가지고 시작합니다. 나머지 채소 카드는 종류마다 6장씩 넣어 정원을 만들어 사용합니다.
===아티초크(ARTICHOKE)===
이 카드는 단독으로 낼 수 없습니다. 게임을 시작할 때 카드 더미에 10장을 가지고 시작합니다.
좋아!
줄기가 가려워!
버려주길 기다릴께!
마음 아프게 하지 말아줘!
나한테 가시가 있다는 거 알고 있었어?!
===가지(EGGPLANT)===
아티초크 1장과 이 카드를 묻습니다. 각 플레이어는 손에서 카드 2장을 골라 자신의 왼쪽 플레이어에게 넘깁니다.
===감자(POTATO) ===
내 카드 더미 맨 위의 카드를 공개하여 아티초크라면 묻고 아니면 버립니다.
===당근(CARROT)===
아티초크 2장과 이 카드를 묻습니다. 같은 차례에 이 카드 이외의 다른 카드를 낼 수는 없습니다.
===리크(LEEK)===
상대 1명을 선택해 카드 더미 맨 위의 카드를 공개하여 내 손으로 가져오거나 그 상대의 버린 카드 더미에 놓습니다.
===브로콜리(BROCCOLI)===
손에 아티초크가 3장 이상이라면 아티초크 1장을 묻습니다.
===비트(BEET)===
상대 1명을 지정하고, 나와 상대의 손에서 각각 무작위로 카드 1장을 공개합니다. 나와 상대의 카드가 둘 다 아티초크라면 두 카드를 모두 묻고, 아니라면 서로 맞바꿉니다.
===완두콩(PEAS)===
정원 카드 더미에서 카드 2장을 공개하여 원하는 1장을 내 버린 카드 더미에, 나머지 1장은 원하는 상대의 버린 카드 더미에 놓습니다.
===양파(ONIONS)===
아티초크 1장을 묻은 뒤 이 카드를 다른 플레이어의 버린 카드 더미에 놓습니다.
===옥수수(CORN)===
아티초크 1장과 이 카드를 함께 내고, 정원의 카드 1장을 골라 내 카드 더미 맨 위에 놓습니다.
===피망(PEPPER)===
내 버린 카드 더미의 카드 1장을 골라 내 카드 더미 맨 위에 올립니다.
===루바브(RHUBARB) - 프로모===
이 카드를 묻고 정원의 카드를 모두 교체한 뒤 카드 1장을 수확합니다. (정원에 있던 카드는 정원 카드 더미 밑으로 되돌립니다.)
94e102842669dd7ea0258c78ae281225367a4172
Tips abandonallartichokes
0
200
1444
1305
2023-03-14T04:34:11Z
Ciwlx
8802
wikitext
text/x-wiki
아티초크 버리기에는 크게보아 2가지 전략이 있습니다. 덱에서 모든 아티초크를 없애는 것과, 손에 아티초크가 없을 가능성이 높이는 큰 덱을 사용하는 것입니다..
== 초반에 좋은 카드 ==
당근 - 손에 사용할 다른 카드가 없으니, 대가 없이 2개의 아티초크를 묻을 수 있습니다.
감자 - 첫번째 라운드에서는 아티초크를 묻을 가능성이 높습니다.
브로콜리 - 3개의 아티초크를 가지고 있는 경우가 많습니다.
가지 - 아티초크 하나를 묻을 수 있고, 나머지를 넘겨줄 수 있습니다.
비트 - 내 손에서 뽑은 무작위 카드가 아티초크일 확률이 높습니다.
== 후반에 좋은 카드 ==
리크 - 상대에게서 아티초크가 아닌 채소 카드를 가져올 수 있습니다.
가지 - 손에 아티초크가 3개 이상 있으면 하나는 묻고 2장을 넘겨줄 수 있습니다. 운이 좋다면 상대에게서 아티초크가 아닌 카드를 받을 수 있습니다.
피망 - 덱을 건드려서 아티초크가 아닌 채소가 많이 뽑히게 할 수 있습니다. 감자와 함께 써서 아티초크를 묻을 수도 있습니다.
비트 - 손에 아티초크만 남아 있을 때 비트를 사용하면 아티초크를 넘겨주거나 묻을 수 있습니다. 상대에게서 좋은 카드를 얻어올 수도 있습니다.
== 아티초크 없애기 전략에 좋은 카드 ==
당근, 양파, 가지 - 아티초크를 묻을 수 있습니다.
== 덱 키우기 전략에 좋은 카드 ==
옥수수 - 덱에 카드를 한 장 더 넣습니다. 그러나 사용하려면 아티초크를 가지고 있어야만 합니다.
완두콩 - 덱에 카드를 한 장 더 넣습니다. 그러나 상대에게도 채소 카드를 줍니다.
피망 - 덱을 건드려서 아티초크가 아닌 채소가 많이 뽑히게 할 수 있습니다.
f2b146e4d1bad9d52f57496cd8f016efbb9a9c87
Tipwingspan
0
246
1445
2023-03-17T11:01:41Z
Tomatocheeze
8790
윙스팬 tip문서 번역
wikitext
text/x-wiki
소개
Wingspan은 핵심적으로 엔진 빌딩 리소스 매니지먼트 게임입니다. 게임에서 가장 제한된 자원은 액션입니다. 각 게임은 26개(8+7+6+5)의 액션으로 제한됩니다. 그러므로 일반적으로 말해, 당신은 모든 액션에서 최대한의 이득을 얻기를 원합니다. 특정 행동(먹이 얻기, 알 낳기, 카드 뽑기)을 취하기 전에 갈색 파워 버드를 플레이하세요. 그러면 그 행동에서 더 많은 것을 얻을 수 있습니다. 핑크 파워 버드를 가능한 한 빨리 플레이하여 여러 번 트리거 될 수 있도록 합니다. 물론, 이에 예외가 있습니다. 예를 들어, 당신이 라운드 종료 목표를 위해 랭킹을 올리는 것이 필요한 경우가 있습니다.
게임 초반
게임이 시작될 때, 각 라운드 종료 목표를 분석하는 시간을 가질 필요가 있습니다. 그들은 당신이 어떤 것을 추구해야하는지 크게 결정하기 때문입니다. 알 목표가 많다면, 초원에 더 많은 투자를 하는 것이 좋은 생각일 수 있습니다. 새 목표가 많다면, 숲에 더 많은 투자를 하는 것이 더 나을 수 있습니다. 이 두 가지는 많이 단순화 된 것입니다. 일반적으로 대부분의 게임에서 모든 서식지에서 새를 건설하고 모든 액션을 취할 것입니다. 많은 다른 중요한 고려 사항이 있습니다:
• 세 개 또는 네 개의 둥지 특정 목표는 별 모양 둥지 새가 더 강해지도록합니다.
• 어떤 둥지 목표가 존재하는지 고려하고 해당 둥지 유형의 새를 보유하고 플레이하는 것이 좋습니다.
• 위치 기반 목표 (특정 서식지에 알이나 새)는 이동하는 새들(서식지 간 이동하는 새)이 더 강해지도록합니다.
• 위의 모든 것을 고려할 때, 특정 핑크 파워 버드도 강해집니다. 왜냐하면 상대방은 이러한 액션을 취하거나 라운드 종료 목표를 포기해야하기 때문입니다.
• 4인용 게임에서는 마지막 목표가 더 많은 점수를 주기 때문에 더 중요하게 생각하십시오. 첫 번째 또는 두 번째 목표를 건너 뛰어서 마지막 것을 이기기 위한 위치를 잡을 수 있다면 그것은 문제가 되지 않습니다. 2 또는 3 인용 게임에서는 목표가 동등하며, 2 등과 3 등의 상금은 1 등과 동일한 속도로 커집니다.
보너스 카드를 개인적인 종료 게임 목표로 생각해 보십시오. 보너스 카드 중 하나가 마지막 라운드 종료 목표와 일치하는지 고려하여 그 가치를 높일 수 있습니다.
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
• 갈색과 분홍색 힘을 가진 새들은 그들의 힘을 작동시킬 수 있는 더 많은 시간이 있는 초기 게임에서 이상적입니다. 더 구체적으로, 당신은 추가적인 카드, 음식, 그리고 계란을 생성하는 힘을 원합니다. 그걸 염두에 두고요.
•• 카드: 이것은 가장 중요한 자원입니다. 좋은 카드 엔진을 가지면 자주 플레이하고 싶은 새를 찾으면서 턱 포인트를 얻을 수 있습니다.
•• 식량: 여러분은 좋은 카드를 찾고 음식을 위해 버려야 할 카드를 찾기 전에는 어떤 음식이 필요한지 모릅니다. 게임 진행 중에는 음식보다 훨씬 많은 카드를 뽑아(버리며)야 합니다. 선택이 가능하다면, 식량을 캐싱하는 것은 대부분 나중에 마지막 몇 턴에 남아있는 조류와 식량 양에 따라 항상 더 나쁩니다.
•• 알: 다른 자원들과 비교했을 때, 알은 게임의 끝까지 가치가 덜하지만, 카드와 음식은 그렇지 않습니다. 그러나, 알을 얻는 방법은 다른 자원과는 다릅니다. 알을 얻을 때는 다른 자원보다 하나 더 많이 받게 되는데, 이를 고려해서 게임 초반에는 알을 사용해 카드를 뽑는 것이 좋습니다. 게임 후반에는 상황에 따라 생각해야 합니다.
• 시작할 떼 가장 좋은 새들은 음식이나 카드를 주는 것입니다. 둘 다 얻으면, 초기 게임이 매우 원활하게 진행됩니다. 물론 이 결정을 내릴 때 각 새의 비용을 고려해야 합니다. 3원 비용의 음식 생산자는 초기에 좋을 수 있지만, 다른 새들을 플레이하는 능력에 어떤 영향을 미칠지 고려해야 합니다.
• 만약 선공을 하는 경우에는, 보이는 새들 중에서 선택할 수 있기 때문에 손에 있는 새들보다 시작하기에 더 좋은 새를 얻을 수 있습니다. 첫 턴에 강력한 새를 뽑는 것도 문제가 되지 않습니다.
• 시작할 때, 보통 손에 있는 새들 중 하나에서 세 마리까지 보유하면 됩니다. 다섯 마리를 보유하는 것은 절대로 하면 안되며, 네 마리를 보유하는 것은 손이 매우 좋거나 비용이 한 개인 숲 조류 카드가 있고 두 번째 턴에 두 개의 식량을 모으기 위해 버릴 계획이 있다면 합리적입니다.
• 상대방이 당신과 동등하게 혜택을 누리는 행동에 대해서는 조심해야 합니다. 이러한 행동들은 아마도 좋지 않을 가능성이 높습니다.
게임 중반
중반에는 적어도 하나 이상의 목표에 부합하는 조류들을 가지고 작은 자원 엔진을 갖추고 있어야 합니다. 이 단계에서는 다음과 같은 원칙을 따라야 합니다:
• 상대방의 게임판을 정기적으로 체크하고 어떤 목표를 실현할 수 있는 가능성이 있는지 고려합니다. 어떤 목표를 달성하기 위해 투자해야 할 노력과 그것을 이길 가능성, 그리고 더 큰 장기적 이득을 가져올 수 있는 다른 영역과 비교합니다.
•• 상대방의 자원 수와 엔진 파워도 체크해야 합니다. 그렇게 뒤쳐지지 않았다면, 그들의 자원이 자신보다 많이 증가할 가능성이 낮을 수도 있습니다.
• 핑크색 조류도 체크해야 합니다. 경우에 따라 상대방이 보다 가치 있는 자원을 얻지 못하도록 하기 위해 (알이나 포식자) 행동을 건너뛰는 것이 좋을 수도 있습니다. (얻은 식량이 일반적으로 1점보다 더 가치가 있으므로) 하지만 이것은 고려해야 할 하나의 요소일 뿐입니다. 때로는 상대방을 돕는 행동을 피할 수 없지만, 다른 플레이어와 같은 턴에 그것을 수행할 수 있습니다.
• 중반에는 보너스 카드 조류를 플레이하는 것이 좋습니다. 이렇게 하면 목표에 대한 플레이를 할 시간을 더 가질 수 있습니다. 그러나 카드를 너무 일찍 사용하면 그것이 행동이 없다는 점이 당신에게 해를 끼칠 수 있습니다.
• 좋은 카드 뽑기 엔진이 있다면, 우선순위를 정하고 추가적인 조류를 획득해야 합니다. 마지막 라운드에서 큰 조류 체인을 기반으로 계획을 세울 경우 게임의 흐름을 뒤집을 수 있습니다.
엔드 게임
3라운드가 끝나고 최종 라운드가 다가오면 남은 턴을 계획할 수 있어야 합니다. 어떤 목표에 집중해야 할지 최종적인 결정을 내리고 그에 따라 플레이하세요. 가장 높은 등급의 목표를 항상 달성하지 못해도 괜찮습니다. 손에 있는 비목표 새를 플레이하면 더 많은 점수를 얻을 수 있을 수도 있습니다. 새를 플레이하기 위해 음식을 수집하는 각 라운드마다 다른 방법으로 점수를 얻는 기회를 놓치는 것이므로 남은 새를 알로 채우는 것이 좋을 수도 있습니다. 어떤 계획이 가장 많은 점수를 제공하는지 계산할 수 있어야 합니다. 행운을 빕니다!
7ee5dad40302044158f60dc1471d0af05a3636cd
1446
1445
2023-03-17T11:02:41Z
Tomatocheeze
8790
wikitext
text/x-wiki
==소개==
Wingspan은 핵심적으로 엔진 빌딩 리소스 매니지먼트 게임입니다. 게임에서 가장 제한된 자원은 액션입니다. 각 게임은 26개(8+7+6+5)의 액션으로 제한됩니다. 그러므로 일반적으로 말해, 당신은 모든 액션에서 최대한의 이득을 얻기를 원합니다. 특정 행동(먹이 얻기, 알 낳기, 카드 뽑기)을 취하기 전에 갈색 파워 버드를 플레이하세요. 그러면 그 행동에서 더 많은 것을 얻을 수 있습니다. 핑크 파워 버드를 가능한 한 빨리 플레이하여 여러 번 트리거 될 수 있도록 합니다. 물론, 이에 예외가 있습니다. 예를 들어, 당신이 라운드 종료 목표를 위해 랭킹을 올리는 것이 필요한 경우가 있습니다.
==게임 초반==
게임이 시작될 때, 각 라운드 종료 목표를 분석하는 시간을 가질 필요가 있습니다. 그들은 당신이 어떤 것을 추구해야하는지 크게 결정하기 때문입니다. 알 목표가 많다면, 초원에 더 많은 투자를 하는 것이 좋은 생각일 수 있습니다. 새 목표가 많다면, 숲에 더 많은 투자를 하는 것이 더 나을 수 있습니다. 이 두 가지는 많이 단순화 된 것입니다. 일반적으로 대부분의 게임에서 모든 서식지에서 새를 건설하고 모든 액션을 취할 것입니다. 많은 다른 중요한 고려 사항이 있습니다:
• 세 개 또는 네 개의 둥지 특정 목표는 별 모양 둥지 새가 더 강해지도록합니다.
• 어떤 둥지 목표가 존재하는지 고려하고 해당 둥지 유형의 새를 보유하고 플레이하는 것이 좋습니다.
• 위치 기반 목표 (특정 서식지에 알이나 새)는 이동하는 새들(서식지 간 이동하는 새)이 더 강해지도록합니다.
• 위의 모든 것을 고려할 때, 특정 핑크 파워 버드도 강해집니다. 왜냐하면 상대방은 이러한 액션을 취하거나 라운드 종료 목표를 포기해야하기 때문입니다.
• 4인용 게임에서는 마지막 목표가 더 많은 점수를 주기 때문에 더 중요하게 생각하십시오. 첫 번째 또는 두 번째 목표를 건너 뛰어서 마지막 것을 이기기 위한 위치를 잡을 수 있다면 그것은 문제가 되지 않습니다. 2 또는 3 인용 게임에서는 목표가 동등하며, 2 등과 3 등의 상금은 1 등과 동일한 속도로 커집니다.
보너스 카드를 개인적인 종료 게임 목표로 생각해 보십시오. 보너스 카드 중 하나가 마지막 라운드 종료 목표와 일치하는지 고려하여 그 가치를 높일 수 있습니다.
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
• 갈색과 분홍색 힘을 가진 새들은 그들의 힘을 작동시킬 수 있는 더 많은 시간이 있는 초기 게임에서 이상적입니다. 더 구체적으로, 당신은 추가적인 카드, 음식, 그리고 계란을 생성하는 힘을 원합니다. 그걸 염두에 두고요.
•• 카드: 이것은 가장 중요한 자원입니다. 좋은 카드 엔진을 가지면 자주 플레이하고 싶은 새를 찾으면서 턱 포인트를 얻을 수 있습니다.
•• 식량: 여러분은 좋은 카드를 찾고 음식을 위해 버려야 할 카드를 찾기 전에는 어떤 음식이 필요한지 모릅니다. 게임 진행 중에는 음식보다 훨씬 많은 카드를 뽑아(버리며)야 합니다. 선택이 가능하다면, 식량을 캐싱하는 것은 대부분 나중에 마지막 몇 턴에 남아있는 조류와 식량 양에 따라 항상 더 나쁩니다.
•• 알: 다른 자원들과 비교했을 때, 알은 게임의 끝까지 가치가 덜하지만, 카드와 음식은 그렇지 않습니다. 그러나, 알을 얻는 방법은 다른 자원과는 다릅니다. 알을 얻을 때는 다른 자원보다 하나 더 많이 받게 되는데, 이를 고려해서 게임 초반에는 알을 사용해 카드를 뽑는 것이 좋습니다. 게임 후반에는 상황에 따라 생각해야 합니다.
• 시작할 떼 가장 좋은 새들은 음식이나 카드를 주는 것입니다. 둘 다 얻으면, 초기 게임이 매우 원활하게 진행됩니다. 물론 이 결정을 내릴 때 각 새의 비용을 고려해야 합니다. 3원 비용의 음식 생산자는 초기에 좋을 수 있지만, 다른 새들을 플레이하는 능력에 어떤 영향을 미칠지 고려해야 합니다.
• 만약 선공을 하는 경우에는, 보이는 새들 중에서 선택할 수 있기 때문에 손에 있는 새들보다 시작하기에 더 좋은 새를 얻을 수 있습니다. 첫 턴에 강력한 새를 뽑는 것도 문제가 되지 않습니다.
• 시작할 때, 보통 손에 있는 새들 중 하나에서 세 마리까지 보유하면 됩니다. 다섯 마리를 보유하는 것은 절대로 하면 안되며, 네 마리를 보유하는 것은 손이 매우 좋거나 비용이 한 개인 숲 조류 카드가 있고 두 번째 턴에 두 개의 식량을 모으기 위해 버릴 계획이 있다면 합리적입니다.
• 상대방이 당신과 동등하게 혜택을 누리는 행동에 대해서는 조심해야 합니다. 이러한 행동들은 아마도 좋지 않을 가능성이 높습니다.
==게임 중반==
중반에는 적어도 하나 이상의 목표에 부합하는 조류들을 가지고 작은 자원 엔진을 갖추고 있어야 합니다. 이 단계에서는 다음과 같은 원칙을 따라야 합니다:
• 상대방의 게임판을 정기적으로 체크하고 어떤 목표를 실현할 수 있는 가능성이 있는지 고려합니다. 어떤 목표를 달성하기 위해 투자해야 할 노력과 그것을 이길 가능성, 그리고 더 큰 장기적 이득을 가져올 수 있는 다른 영역과 비교합니다.
•• 상대방의 자원 수와 엔진 파워도 체크해야 합니다. 그렇게 뒤쳐지지 않았다면, 그들의 자원이 자신보다 많이 증가할 가능성이 낮을 수도 있습니다.
• 핑크색 조류도 체크해야 합니다. 경우에 따라 상대방이 보다 가치 있는 자원을 얻지 못하도록 하기 위해 (알이나 포식자) 행동을 건너뛰는 것이 좋을 수도 있습니다. (얻은 식량이 일반적으로 1점보다 더 가치가 있으므로) 하지만 이것은 고려해야 할 하나의 요소일 뿐입니다. 때로는 상대방을 돕는 행동을 피할 수 없지만, 다른 플레이어와 같은 턴에 그것을 수행할 수 있습니다.
• 중반에는 보너스 카드 조류를 플레이하는 것이 좋습니다. 이렇게 하면 목표에 대한 플레이를 할 시간을 더 가질 수 있습니다. 그러나 카드를 너무 일찍 사용하면 그것이 행동이 없다는 점이 당신에게 해를 끼칠 수 있습니다.
• 좋은 카드 뽑기 엔진이 있다면, 우선순위를 정하고 추가적인 조류를 획득해야 합니다. 마지막 라운드에서 큰 조류 체인을 기반으로 계획을 세울 경우 게임의 흐름을 뒤집을 수 있습니다.
==엔드 게임==
3라운드가 끝나고 최종 라운드가 다가오면 남은 턴을 계획할 수 있어야 합니다. 어떤 목표에 집중해야 할지 최종적인 결정을 내리고 그에 따라 플레이하세요. 가장 높은 등급의 목표를 항상 달성하지 못해도 괜찮습니다. 손에 있는 비목표 새를 플레이하면 더 많은 점수를 얻을 수 있을 수도 있습니다. 새를 플레이하기 위해 음식을 수집하는 각 라운드마다 다른 방법으로 점수를 얻는 기회를 놓치는 것이므로 남은 새를 알로 채우는 것이 좋을 수도 있습니다. 어떤 계획이 가장 많은 점수를 제공하는지 계산할 수 있어야 합니다. 행운을 빕니다!
24b07ca88fdc7cab31d83ad1ba3f81132fef04ce
Tips wingspan
0
247
1447
2023-03-17T11:04:12Z
Tomatocheeze
8790
새 문서: ==소개== Wingspan은 핵심적으로 엔진 빌딩 리소스 매니지먼트 게임입니다. 게임에서 가장 제한된 자원은 액션입니다. 각 게임은 26개(8+7+6+5)의 액션으로 제한됩니다. 그러므로 일반적으로 말해, 당신은 모든 액션에서 최대한의 이득을 얻기를 원합니다. 특정 행동(먹이 얻기, 알 낳기, 카드 뽑기)을 취하기 전에 갈색 파워 버드를 플레이하세요. 그러면 그 행동에서 더 많...
wikitext
text/x-wiki
==소개==
Wingspan은 핵심적으로 엔진 빌딩 리소스 매니지먼트 게임입니다. 게임에서 가장 제한된 자원은 액션입니다. 각 게임은 26개(8+7+6+5)의 액션으로 제한됩니다. 그러므로 일반적으로 말해, 당신은 모든 액션에서 최대한의 이득을 얻기를 원합니다. 특정 행동(먹이 얻기, 알 낳기, 카드 뽑기)을 취하기 전에 갈색 파워 버드를 플레이하세요. 그러면 그 행동에서 더 많은 것을 얻을 수 있습니다. 핑크 파워 버드를 가능한 한 빨리 플레이하여 여러 번 트리거 될 수 있도록 합니다. 물론, 이에 예외가 있습니다. 예를 들어, 당신이 라운드 종료 목표를 위해 랭킹을 올리는 것이 필요한 경우가 있습니다.
==게임 초반==
게임이 시작될 때, 각 라운드 종료 목표를 분석하는 시간을 가질 필요가 있습니다. 그들은 당신이 어떤 것을 추구해야하는지 크게 결정하기 때문입니다. 알 목표가 많다면, 초원에 더 많은 투자를 하는 것이 좋은 생각일 수 있습니다. 새 목표가 많다면, 숲에 더 많은 투자를 하는 것이 더 나을 수 있습니다. 이 두 가지는 많이 단순화 된 것입니다. 일반적으로 대부분의 게임에서 모든 서식지에서 새를 건설하고 모든 액션을 취할 것입니다. 많은 다른 중요한 고려 사항이 있습니다:
• 세 개 또는 네 개의 둥지 특정 목표는 별 모양 둥지 새가 더 강해지도록합니다.
• 어떤 둥지 목표가 존재하는지 고려하고 해당 둥지 유형의 새를 보유하고 플레이하는 것이 좋습니다.
• 위치 기반 목표 (특정 서식지에 알이나 새)는 이동하는 새들(서식지 간 이동하는 새)이 더 강해지도록합니다.
• 위의 모든 것을 고려할 때, 특정 핑크 파워 버드도 강해집니다. 왜냐하면 상대방은 이러한 액션을 취하거나 라운드 종료 목표를 포기해야하기 때문입니다.
• 4인용 게임에서는 마지막 목표가 더 많은 점수를 주기 때문에 더 중요하게 생각하십시오. 첫 번째 또는 두 번째 목표를 건너 뛰어서 마지막 것을 이기기 위한 위치를 잡을 수 있다면 그것은 문제가 되지 않습니다. 2 또는 3 인용 게임에서는 목표가 동등하며, 2 등과 3 등의 상금은 1 등과 동일한 속도로 커집니다.
보너스 카드를 개인적인 종료 게임 목표로 생각해 보십시오. 보너스 카드 중 하나가 마지막 라운드 종료 목표와 일치하는지 고려하여 그 가치를 높일 수 있습니다.
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
• 갈색과 분홍색 힘을 가진 새들은 그들의 힘을 작동시킬 수 있는 더 많은 시간이 있는 초기 게임에서 이상적입니다. 더 구체적으로, 당신은 추가적인 카드, 음식, 그리고 계란을 생성하는 힘을 원합니다. 그걸 염두에 두고요.
•• 카드: 이것은 가장 중요한 자원입니다. 좋은 카드 엔진을 가지면 자주 플레이하고 싶은 새를 찾으면서 턱 포인트를 얻을 수 있습니다.
•• 식량: 여러분은 좋은 카드를 찾고 음식을 위해 버려야 할 카드를 찾기 전에는 어떤 음식이 필요한지 모릅니다. 게임 진행 중에는 음식보다 훨씬 많은 카드를 뽑아(버리며)야 합니다. 선택이 가능하다면, 식량을 캐싱하는 것은 대부분 나중에 마지막 몇 턴에 남아있는 조류와 식량 양에 따라 항상 더 나쁩니다.
•• 알: 다른 자원들과 비교했을 때, 알은 게임의 끝까지 가치가 덜하지만, 카드와 음식은 그렇지 않습니다. 그러나, 알을 얻는 방법은 다른 자원과는 다릅니다. 알을 얻을 때는 다른 자원보다 하나 더 많이 받게 되는데, 이를 고려해서 게임 초반에는 알을 사용해 카드를 뽑는 것이 좋습니다. 게임 후반에는 상황에 따라 생각해야 합니다.
• 시작할 떼 가장 좋은 새들은 음식이나 카드를 주는 것입니다. 둘 다 얻으면, 초기 게임이 매우 원활하게 진행됩니다. 물론 이 결정을 내릴 때 각 새의 비용을 고려해야 합니다. 3원 비용의 음식 생산자는 초기에 좋을 수 있지만, 다른 새들을 플레이하는 능력에 어떤 영향을 미칠지 고려해야 합니다.
• 만약 선공을 하는 경우에는, 보이는 새들 중에서 선택할 수 있기 때문에 손에 있는 새들보다 시작하기에 더 좋은 새를 얻을 수 있습니다. 첫 턴에 강력한 새를 뽑는 것도 문제가 되지 않습니다.
• 시작할 때, 보통 손에 있는 새들 중 하나에서 세 마리까지 보유하면 됩니다. 다섯 마리를 보유하는 것은 절대로 하면 안되며, 네 마리를 보유하는 것은 손이 매우 좋거나 비용이 한 개인 숲 조류 카드가 있고 두 번째 턴에 두 개의 식량을 모으기 위해 버릴 계획이 있다면 합리적입니다.
• 상대방이 당신과 동등하게 혜택을 누리는 행동에 대해서는 조심해야 합니다. 이러한 행동들은 아마도 좋지 않을 가능성이 높습니다.
==게임 중반==
중반에는 적어도 하나 이상의 목표에 부합하는 조류들을 가지고 작은 자원 엔진을 갖추고 있어야 합니다. 이 단계에서는 다음과 같은 원칙을 따라야 합니다:
• 상대방의 게임판을 정기적으로 체크하고 어떤 목표를 실현할 수 있는 가능성이 있는지 고려합니다. 어떤 목표를 달성하기 위해 투자해야 할 노력과 그것을 이길 가능성, 그리고 더 큰 장기적 이득을 가져올 수 있는 다른 영역과 비교합니다.
•• 상대방의 자원 수와 엔진 파워도 체크해야 합니다. 그렇게 뒤쳐지지 않았다면, 그들의 자원이 자신보다 많이 증가할 가능성이 낮을 수도 있습니다.
• 핑크색 조류도 체크해야 합니다. 경우에 따라 상대방이 보다 가치 있는 자원을 얻지 못하도록 하기 위해 (알이나 포식자) 행동을 건너뛰는 것이 좋을 수도 있습니다. (얻은 식량이 일반적으로 1점보다 더 가치가 있으므로) 하지만 이것은 고려해야 할 하나의 요소일 뿐입니다. 때로는 상대방을 돕는 행동을 피할 수 없지만, 다른 플레이어와 같은 턴에 그것을 수행할 수 있습니다.
• 중반에는 보너스 카드 조류를 플레이하는 것이 좋습니다. 이렇게 하면 목표에 대한 플레이를 할 시간을 더 가질 수 있습니다. 그러나 카드를 너무 일찍 사용하면 그것이 행동이 없다는 점이 당신에게 해를 끼칠 수 있습니다.
• 좋은 카드 뽑기 엔진이 있다면, 우선순위를 정하고 추가적인 조류를 획득해야 합니다. 마지막 라운드에서 큰 조류 체인을 기반으로 계획을 세울 경우 게임의 흐름을 뒤집을 수 있습니다.
==엔드 게임==
3라운드가 끝나고 최종 라운드가 다가오면 남은 턴을 계획할 수 있어야 합니다. 어떤 목표에 집중해야 할지 최종적인 결정을 내리고 그에 따라 플레이하세요. 가장 높은 등급의 목표를 항상 달성하지 못해도 괜찮습니다. 손에 있는 비목표 새를 플레이하면 더 많은 점수를 얻을 수 있을 수도 있습니다. 새를 플레이하기 위해 음식을 수집하는 각 라운드마다 다른 방법으로 점수를 얻는 기회를 놓치는 것이므로 남은 새를 알로 채우는 것이 좋을 수도 있습니다. 어떤 계획이 가장 많은 점수를 제공하는지 계산할 수 있어야 합니다. 행운을 빕니다!
24b07ca88fdc7cab31d83ad1ba3f81132fef04ce
1449
1447
2023-03-17T11:11:52Z
Tomatocheeze
8790
wikitext
text/x-wiki
==소개==
Wingspan은 핵심적으로 엔진 빌딩 리소스 매니지먼트 게임입니다. 게임에서 가장 제한된 자원은 액션입니다. 각 게임은 26개(8+7+6+5)의 액션으로 제한됩니다. 그러므로 일반적으로 말해, 당신은 모든 액션에서 최대한의 이득을 얻기를 원합니다. 특정 행동(먹이 얻기, 알 낳기, 카드 뽑기)을 취하기 전에 갈색 파워 버드를 플레이하세요. 그러면 그 행동에서 더 많은 것을 얻을 수 있습니다. 핑크 파워 버드를 가능한 한 빨리 플레이하여 여러 번 트리거 될 수 있도록 합니다. 물론, 이에 예외가 있습니다. 예를 들어, 당신이 라운드 종료 목표를 위해 랭킹을 올리는 것이 필요한 경우가 있습니다.
==게임 초반==
게임이 시작될 때, 각 라운드 종료 목표를 분석하는 시간을 가질 필요가 있습니다. 그들은 당신이 어떤 것을 추구해야하는지 크게 결정하기 때문입니다. 알 목표가 많다면, 초원에 더 많은 투자를 하는 것이 좋은 생각일 수 있습니다. 새 목표가 많다면, 숲에 더 많은 투자를 하는 것이 더 나을 수 있습니다. 이 두 가지는 많이 단순화 된 것입니다. 일반적으로 대부분의 게임에서 모든 서식지에서 새를 건설하고 모든 액션을 취할 것입니다. 많은 다른 중요한 고려 사항이 있습니다:
• 세 개 또는 네 개의 둥지 특정 목표는 별 모양 둥지 새가 더 강해지도록합니다.
• 어떤 둥지 목표가 존재하는지 고려하고 해당 둥지 유형의 새를 보유하고 플레이하는 것이 좋습니다.
• 위치 기반 목표 (특정 서식지에 알이나 새)는 이동하는 새들(서식지 간 이동하는 새)이 더 강해지도록합니다.
• 위의 모든 것을 고려할 때, 특정 핑크 파워 버드도 강해집니다. 왜냐하면 상대방은 이러한 액션을 취하거나 라운드 종료 목표를 포기해야하기 때문입니다.
• 4인용 게임에서는 마지막 목표가 더 많은 점수를 주기 때문에 더 중요하게 생각하십시오. 첫 번째 또는 두 번째 목표를 건너 뛰어서 마지막 것을 이기기 위한 위치를 잡을 수 있다면 그것은 문제가 되지 않습니다. 2 또는 3 인용 게임에서는 목표가 동등하며, 2 등과 3 등의 상금은 1 등과 동일한 속도로 커집니다.
보너스 카드를 개인적인 종료 게임 목표로 생각해 보십시오. 보너스 카드 중 하나가 마지막 라운드 종료 목표와 일치하는지 고려하여 그 가치를 높일 수 있습니다.
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
• 갈색과 분홍색 힘을 가진 새들은 그들의 힘을 작동시킬 수 있는 더 많은 시간이 있는 초기 게임에서 이상적입니다. 더 구체적으로, 당신은 추가적인 카드, 음식, 그리고 계란을 생성하는 힘을 원합니다. 그걸 염두에 두고요.
•• 카드: 이것은 가장 중요한 자원입니다. 좋은 카드 엔진을 가지면 자주 플레이하고 싶은 새를 찾으면서 턱 포인트를 얻을 수 있습니다.
•• 식량: 여러분은 좋은 카드를 찾고 음식을 위해 버려야 할 카드를 찾기 전에는 어떤 음식이 필요한지 모릅니다. 게임 진행 중에는 음식보다 훨씬 많은 카드를 뽑아(버리며)야 합니다. 선택이 가능하다면, 식량을 캐싱하는 것은 대부분 나중에 마지막 몇 턴에 남아있는 조류와 식량 양에 따라 항상 더 나쁩니다.
•• 알: 다른 자원들과 비교했을 때, 알은 게임의 끝까지 가치가 덜하지만, 카드와 음식은 그렇지 않습니다. 그러나, 알을 얻는 방법은 다른 자원과는 다릅니다. 알을 얻을 때는 다른 자원보다 하나 더 많이 받게 되는데, 이를 고려해서 게임 초반에는 알을 사용해 카드를 뽑는 것이 좋습니다. 게임 후반에는 상황에 따라 생각해야 합니다.
• 시작할 떼 가장 좋은 새들은 음식이나 카드를 주는 것입니다. 둘 다 얻으면, 초기 게임이 매우 원활하게 진행됩니다. 물론 이 결정을 내릴 때 각 새의 비용을 고려해야 합니다. 3원 비용의 음식 생산자는 초기에 좋을 수 있지만, 다른 새들을 플레이하는 능력에 어떤 영향을 미칠지 고려해야 합니다.
• 만약 선공을 하는 경우에는, 보이는 새들 중에서 선택할 수 있기 때문에 손에 있는 새들보다 시작하기에 더 좋은 새를 얻을 수 있습니다. 첫 턴에 강력한 새를 뽑는 것도 문제가 되지 않습니다.
• 시작할 때, 보통 손에 있는 새들 중 하나에서 세 마리까지 보유하면 됩니다. 다섯 마리를 보유하는 것은 절대로 하면 안되며, 네 마리를 보유하는 것은 손이 매우 좋거나 비용이 한 개인 숲 조류 카드가 있고 두 번째 턴에 두 개의 식량을 모으기 위해 버릴 계획이 있다면 합리적입니다.
• 상대방이 당신과 동등하게 혜택을 누리는 행동에 대해서는 조심해야 합니다. 이러한 행동들은 아마도 좋지 않을 가능성이 높습니다.
==게임 중반==
중반에는 적어도 하나 이상의 목표에 부합하는 조류들을 가지고 작은 자원 엔진을 갖추고 있어야 합니다. 이 단계에서는 다음과 같은 원칙을 따라야 합니다:
• 상대방의 게임판을 정기적으로 체크하고 어떤 목표를 실현할 수 있는 가능성이 있는지 고려합니다. 어떤 목표를 달성하기 위해 투자해야 할 노력과 그것을 이길 가능성, 그리고 더 큰 장기적 이득을 가져올 수 있는 다른 영역과 비교합니다.
•• 상대방의 자원 수와 엔진 파워도 체크해야 합니다. 그렇게 뒤쳐지지 않았다면, 그들의 자원이 자신보다 많이 증가할 가능성이 낮을 수도 있습니다.
• 핑크색 조류도 체크해야 합니다. 경우에 따라 상대방이 보다 가치 있는 자원을 얻지 못하도록 하기 위해 (알이나 포식자) 행동을 건너뛰는 것이 좋을 수도 있습니다. (얻은 식량이 일반적으로 1점보다 더 가치가 있으므로) 하지만 이것은 고려해야 할 하나의 요소일 뿐입니다. 때로는 상대방을 돕는 행동을 피할 수 없지만, 다른 플레이어와 같은 턴에 그것을 수행할 수 있습니다.
• 중반에는 보너스 카드 조류를 플레이하는 것이 좋습니다. 이렇게 하면 목표에 대한 플레이를 할 시간을 더 가질 수 있습니다. 그러나 카드를 너무 일찍 사용하면 그것이 행동이 없다는 점이 당신에게 해를 끼칠 수 있습니다.
• 좋은 카드 뽑기 엔진이 있다면, 우선순위를 정하고 추가적인 조류를 획득해야 합니다. 마지막 라운드에서 큰 조류 체인을 기반으로 계획을 세울 경우 게임의 흐름을 뒤집을 수 있습니다.
==엔드 게임==
3라운드가 끝나고 최종 라운드가 다가오면 남은 턴을 계획할 수 있어야 합니다. 어떤 목표에 집중해야 할지 최종적인 결정을 내리고 그에 따라 플레이하세요. 가장 높은 등급의 목표를 항상 달성하지 못해도 괜찮습니다. 손에 있는 비목표 새를 플레이하면 더 많은 점수를 얻을 수 있을 수도 있습니다. 새를 플레이하기 위해 음식을 수집하는 각 라운드마다 다른 방법으로 점수를 얻는 기회를 놓치는 것이므로 남은 새를 알로 채우는 것이 좋을 수도 있습니다. 어떤 계획이 가장 많은 점수를 제공하는지 계산할 수 있어야 합니다. 행운을 빕니다!
53ea8b1c8451e3e85efa21d026076ec824a6c2cb
1450
1449
2023-03-17T11:12:02Z
Tomatocheeze
8790
wikitext
text/x-wiki
==소개==
Wingspan은 핵심적으로 엔진 빌딩 리소스 매니지먼트 게임입니다. 게임에서 가장 제한된 자원은 액션입니다. 각 게임은 26개(8+7+6+5)의 액션으로 제한됩니다. 그러므로 일반적으로 말해, 당신은 모든 액션에서 최대한의 이득을 얻기를 원합니다. 특정 행동(먹이 얻기, 알 낳기, 카드 뽑기)을 취하기 전에 갈색 파워 버드를 플레이하세요. 그러면 그 행동에서 더 많은 것을 얻을 수 있습니다. 핑크 파워 버드를 가능한 한 빨리 플레이하여 여러 번 트리거 될 수 있도록 합니다. 물론, 이에 예외가 있습니다. 예를 들어, 당신이 라운드 종료 목표를 위해 랭킹을 올리는 것이 필요한 경우가 있습니다.
==게임 초반==
게임이 시작될 때, 각 라운드 종료 목표를 분석하는 시간을 가질 필요가 있습니다. 그들은 당신이 어떤 것을 추구해야하는지 크게 결정하기 때문입니다. 알 목표가 많다면, 초원에 더 많은 투자를 하는 것이 좋은 생각일 수 있습니다. 새 목표가 많다면, 숲에 더 많은 투자를 하는 것이 더 나을 수 있습니다. 이 두 가지는 많이 단순화 된 것입니다. 일반적으로 대부분의 게임에서 모든 서식지에서 새를 건설하고 모든 액션을 취할 것입니다. 많은 다른 중요한 고려 사항이 있습니다:
• 세 개 또는 네 개의 둥지 특정 목표는 별 모양 둥지 새가 더 강해지도록합니다.
• 어떤 둥지 목표가 존재하는지 고려하고 해당 둥지 유형의 새를 보유하고 플레이하는 것이 좋습니다.
• 위치 기반 목표 (특정 서식지에 알이나 새)는 이동하는 새들(서식지 간 이동하는 새)이 더 강해지도록합니다.
• 위의 모든 것을 고려할 때, 특정 핑크 파워 버드도 강해집니다. 왜냐하면 상대방은 이러한 액션을 취하거나 라운드 종료 목표를 포기해야하기 때문입니다.
• 4인용 게임에서는 마지막 목표가 더 많은 점수를 주기 때문에 더 중요하게 생각하십시오. 첫 번째 또는 두 번째 목표를 건너 뛰어서 마지막 것을 이기기 위한 위치를 잡을 수 있다면 그것은 문제가 되지 않습니다. 2 또는 3 인용 게임에서는 목표가 동등하며, 2 등과 3 등의 상금은 1 등과 동일한 속도로 커집니다.
보너스 카드를 개인적인 종료 게임 목표로 생각해 보십시오. 보너스 카드 중 하나가 마지막 라운드 종료 목표와 일치하는지 고려하여 그 가치를 높일 수 있습니다.
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
• 갈색과 분홍색 힘을 가진 새들은 그들의 힘을 작동시킬 수 있는 더 많은 시간이 있는 초기 게임에서 이상적입니다. 더 구체적으로, 당신은 추가적인 카드, 음식, 그리고 계란을 생성하는 힘을 원합니다. 그걸 염두에 두고요.
•• 카드: 이것은 가장 중요한 자원입니다. 좋은 카드 엔진을 가지면 자주 플레이하고 싶은 새를 찾으면서 턱 포인트를 얻을 수 있습니다.
•• 식량: 여러분은 좋은 카드를 찾고 음식을 위해 버려야 할 카드를 찾기 전에는 어떤 음식이 필요한지 모릅니다. 게임 진행 중에는 음식보다 훨씬 많은 카드를 뽑아(버리며)야 합니다. 선택이 가능하다면, 식량을 캐싱하는 것은 대부분 나중에 마지막 몇 턴에 남아있는 조류와 식량 양에 따라 항상 더 나쁩니다.
•• 알: 다른 자원들과 비교했을 때, 알은 게임의 끝까지 가치가 덜하지만, 카드와 음식은 그렇지 않습니다. 그러나, 알을 얻는 방법은 다른 자원과는 다릅니다. 알을 얻을 때는 다른 자원보다 하나 더 많이 받게 되는데, 이를 고려해서 게임 초반에는 알을 사용해 카드를 뽑는 것이 좋습니다. 게임 후반에는 상황에 따라 생각해야 합니다.
• 시작할 떼 가장 좋은 새들은 음식이나 카드를 주는 것입니다. 둘 다 얻으면, 초기 게임이 매우 원활하게 진행됩니다. 물론 이 결정을 내릴 때 각 새의 비용을 고려해야 합니다. 3원 비용의 음식 생산자는 초기에 좋을 수 있지만, 다른 새들을 플레이하는 능력에 어떤 영향을 미칠지 고려해야 합니다.
• 만약 선공을 하는 경우에는, 보이는 새들 중에서 선택할 수 있기 때문에 손에 있는 새들보다 시작하기에 더 좋은 새를 얻을 수 있습니다. 첫 턴에 강력한 새를 뽑는 것도 문제가 되지 않습니다.
• 시작할 때, 보통 손에 있는 새들 중 하나에서 세 마리까지 보유하면 됩니다. 다섯 마리를 보유하는 것은 절대로 하면 안되며, 네 마리를 보유하는 것은 손이 매우 좋거나 비용이 한 개인 숲 조류 카드가 있고 두 번째 턴에 두 개의 식량을 모으기 위해 버릴 계획이 있다면 합리적입니다.
• 상대방이 당신과 동등하게 혜택을 누리는 행동에 대해서는 조심해야 합니다. 이러한 행동들은 아마도 좋지 않을 가능성이 높습니다.
==게임 중반==
중반에는 적어도 하나 이상의 목표에 부합하는 조류들을 가지고 작은 자원 엔진을 갖추고 있어야 합니다. 이 단계에서는 다음과 같은 원칙을 따라야 합니다:
• 상대방의 게임판을 정기적으로 체크하고 어떤 목표를 실현할 수 있는 가능성이 있는지 고려합니다. 어떤 목표를 달성하기 위해 투자해야 할 노력과 그것을 이길 가능성, 그리고 더 큰 장기적 이득을 가져올 수 있는 다른 영역과 비교합니다.
•• 상대방의 자원 수와 엔진 파워도 체크해야 합니다. 그렇게 뒤쳐지지 않았다면, 그들의 자원이 자신보다 많이 증가할 가능성이 낮을 수도 있습니다.
• 핑크색 조류도 체크해야 합니다. 경우에 따라 상대방이 보다 가치 있는 자원을 얻지 못하도록 하기 위해 (알이나 포식자) 행동을 건너뛰는 것이 좋을 수도 있습니다. (얻은 식량이 일반적으로 1점보다 더 가치가 있으므로) 하지만 이것은 고려해야 할 하나의 요소일 뿐입니다. 때로는 상대방을 돕는 행동을 피할 수 없지만, 다른 플레이어와 같은 턴에 그것을 수행할 수 있습니다.
• 중반에는 보너스 카드 조류를 플레이하는 것이 좋습니다. 이렇게 하면 목표에 대한 플레이를 할 시간을 더 가질 수 있습니다. 그러나 카드를 너무 일찍 사용하면 그것이 행동이 없다는 점이 당신에게 해를 끼칠 수 있습니다.
• 좋은 카드 뽑기 엔진이 있다면, 우선순위를 정하고 추가적인 조류를 획득해야 합니다. 마지막 라운드에서 큰 조류 체인을 기반으로 계획을 세울 경우 게임의 흐름을 뒤집을 수 있습니다.
==엔드 게임==
3라운드가 끝나고 최종 라운드가 다가오면 남은 턴을 계획할 수 있어야 합니다. 어떤 목표에 집중해야 할지 최종적인 결정을 내리고 그에 따라 플레이하세요. 가장 높은 등급의 목표를 항상 달성하지 못해도 괜찮습니다. 손에 있는 비목표 새를 플레이하면 더 많은 점수를 얻을 수 있을 수도 있습니다. 새를 플레이하기 위해 음식을 수집하는 각 라운드마다 다른 방법으로 점수를 얻는 기회를 놓치는 것이므로 남은 새를 알로 채우는 것이 좋을 수도 있습니다. 어떤 계획이 가장 많은 점수를 제공하는지 계산할 수 있어야 합니다. 행운을 빕니다!
120e7a833f05ec92b87b3a07b8ccc15b7fc8eb9e
1451
1450
2023-03-17T12:23:39Z
Tomatocheeze
8790
wikitext
text/x-wiki
==소개==
Wingspan은 핵심적으로 엔진 빌딩 리소스 매니지먼트 게임입니다. 게임에서 가장 제한된 자원은 액션입니다. 각 게임은 26개(8+7+6+5)의 액션으로 제한됩니다. 그러므로 일반적으로 말해, 당신은 모든 액션에서 최대한의 이득을 얻기를 원합니다. 특정 행동(먹이 얻기, 알 낳기, 카드 뽑기)을 취하기 전에 갈색 파워 버드를 플레이하세요. 그러면 그 행동에서 더 많은 것을 얻을 수 있습니다. 핑크 파워 버드를 가능한 한 빨리 플레이하여 여러 번 트리거 될 수 있도록 합니다. 물론, 이에 예외가 있습니다. 예를 들어, 당신이 라운드 종료 목표를 위해 랭킹을 올리는 것이 필요한 경우가 있습니다.
==게임 초반==
게임이 시작될 때, 각 라운드 종료 목표를 분석하는 시간을 가질 필요가 있습니다. 그들은 당신이 어떤 것을 추구해야하는지 크게 결정하기 때문입니다. 알 목표가 많다면, 초원에 더 많은 투자를 하는 것이 좋은 생각일 수 있습니다. 새 목표가 많다면, 숲에 더 많은 투자를 하는 것이 더 나을 수 있습니다. 이 두 가지는 많이 단순화 된 것입니다. 일반적으로 대부분의 게임에서 모든 서식지에서 새를 건설하고 모든 액션을 취할 것입니다. 많은 다른 중요한 고려 사항이 있습니다:
• 세 개 또는 네 개의 둥지 특정 목표는 별 모양 둥지 새가 더 강해지도록합니다.
• 어떤 둥지 목표가 존재하는지 고려하고 해당 둥지 유형의 새를 보유하고 플레이하는 것이 좋습니다.
• 위치 기반 목표 (특정 서식지에 알이나 새)는 이동하는 새들(서식지 간 이동하는 새)이 더 강해지도록합니다.
• 위의 모든 것을 고려할 때, 특정 핑크 파워 버드도 강해집니다. 왜냐하면 상대방은 이러한 액션을 취하거나 라운드 종료 목표를 포기해야하기 때문입니다.
• 4인용 게임에서는 마지막 목표가 더 많은 점수를 주기 때문에 더 중요하게 생각하십시오. 첫 번째 또는 두 번째 목표를 건너 뛰어서 마지막 것을 이기기 위한 위치를 잡을 수 있다면 그것은 문제가 되지 않습니다. 2 또는 3 인용 게임에서는 목표가 동등하며, 2 등과 3 등의 상금은 1 등과 동일한 속도로 커집니다.
보너스 카드를 개인적인 종료 게임 목표로 생각해 보십시오. 보너스 카드 중 하나가 마지막 라운드 종료 목표와 일치하는지 고려하여 그 가치를 높일 수 있습니다.
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
• 갈색과 분홍색 힘을 가진 새들은 그들의 힘을 작동시킬 수 있는 더 많은 시간이 있는 초기 게임에서 이상적입니다. 더 구체적으로, 당신은 추가적인 카드, 음식, 그리고 계란을 생성하는 힘을 원합니다. 그걸 염두에 두고요.
•• 카드: 이것은 가장 중요한 자원입니다. 좋은 카드 엔진을 가지면 자주 플레이하고 싶은 새를 찾으면서 턱 포인트를 얻을 수 있습니다.
•• 식량: 여러분은 좋은 카드를 찾고 음식을 위해 버려야 할 카드를 찾기 전에는 어떤 음식이 필요한지 모릅니다. 게임 진행 중에는 음식보다 훨씬 많은 카드를 뽑아(버리며)야 합니다. 선택이 가능하다면, 식량을 캐싱하는 것은 대부분 나중에 마지막 몇 턴에 남아있는 조류와 식량 양에 따라 항상 더 나쁩니다.
•• 알: 다른 자원들과 비교했을 때, 알은 게임의 끝까지 가치가 덜하지만, 카드와 음식은 그렇지 않습니다. 그러나, 알을 얻는 방법은 다른 자원과는 다릅니다. 알을 얻을 때는 다른 자원보다 하나 더 많이 받게 되는데, 이를 고려해서 게임 초반에는 알을 사용해 카드를 뽑는 것이 좋습니다. 게임 후반에는 상황에 따라 생각해야 합니다.
• 시작할 떼 가장 좋은 새들은 음식이나 카드를 주는 것입니다. 둘 다 얻으면, 초기 게임이 매우 원활하게 진행됩니다. 물론 이 결정을 내릴 때 각 새의 비용을 고려해야 합니다. 3원 비용의 음식 생산자는 초기에 좋을 수 있지만, 다른 새들을 플레이하는 능력에 어떤 영향을 미칠지 고려해야 합니다.
• 만약 선공을 하는 경우에는, 보이는 새들 중에서 선택할 수 있기 때문에 손에 있는 새들보다 시작하기에 더 좋은 새를 얻을 수 있습니다. 첫 턴에 강력한 새를 뽑는 것도 문제가 되지 않습니다.
• 시작할 때, 보통 손에 있는 새들 중 하나에서 세 마리까지 보유하면 됩니다. 다섯 마리를 보유하는 것은 절대로 하면 안되며, 네 마리를 보유하는 것은 손이 매우 좋거나 비용이 한 개인 숲 조류 카드가 있고 두 번째 턴에 두 개의 식량을 모으기 위해 버릴 계획이 있다면 합리적입니다.
• 상대방이 당신과 동등하게 혜택을 누리는 행동에 대해서는 조심해야 합니다. 이러한 행동들은 아마도 좋지 않을 가능성이 높습니다.
==게임 중반==
중반에는 적어도 하나 이상의 목표에 부합하는 조류들을 가지고 작은 자원 엔진을 갖추고 있어야 합니다. 이 단계에서는 다음과 같은 원칙을 따라야 합니다:
• 상대방의 게임판을 정기적으로 체크하고 어떤 목표를 실현할 수 있는 가능성이 있는지 고려합니다. 어떤 목표를 달성하기 위해 투자해야 할 노력과 그것을 이길 가능성, 그리고 더 큰 장기적 이득을 가져올 수 있는 다른 영역과 비교합니다.
•• 상대방의 자원 수와 엔진 파워도 체크해야 합니다. 그렇게 뒤쳐지지 않았다면, 그들의 자원이 자신보다 많이 증가할 가능성이 낮을 수도 있습니다.
• 핑크색 조류도 체크해야 합니다. 경우에 따라 상대방이 보다 가치 있는 자원을 얻지 못하도록 하기 위해 (알이나 포식자) 행동을 건너뛰는 것이 좋을 수도 있습니다. (얻은 식량이 일반적으로 1점보다 더 가치가 있으므로) 하지만 이것은 고려해야 할 하나의 요소일 뿐입니다. 때로는 상대방을 돕는 행동을 피할 수 없지만, 다른 플레이어와 같은 턴에 그것을 수행할 수 있습니다.
• 중반에는 보너스 카드 조류를 플레이하는 것이 좋습니다. 이렇게 하면 목표에 대한 플레이를 할 시간을 더 가질 수 있습니다. 그러나 카드를 너무 일찍 사용하면 그것이 행동이 없다는 점이 당신에게 해를 끼칠 수 있습니다.
• 좋은 카드 뽑기 엔진이 있다면, 우선순위를 정하고 추가적인 조류를 획득해야 합니다. 마지막 라운드에서 큰 조류 체인을 기반으로 계획을 세울 경우 게임의 흐름을 뒤집을 수 있습니다.
==엔드 게임==
3라운드가 끝나고 최종 라운드가 다가오면 남은 턴을 계획할 수 있어야 합니다. 어떤 목표에 집중해야 할지 최종적인 결정을 내리고 그에 따라 플레이하세요. 가장 높은 등급의 목표를 항상 달성하지 못해도 괜찮습니다. 손에 있는 비목표 새를 플레이하면 더 많은 점수를 얻을 수 있을 수도 있습니다. 새를 플레이하기 위해 음식을 수집하는 각 라운드마다 다른 방법으로 점수를 얻는 기회를 놓치는 것이므로 남은 새를 알로 채우는 것이 좋을 수도 있습니다. 어떤 계획이 가장 많은 점수를 제공하는지 계산할 수 있어야 합니다. 행운을 빕니다!
ce9cbd52a5918aa39159c97f50a41265e8d4be35
토론:Tipwingspan
1
248
1448
2023-03-17T11:09:22Z
Tomatocheeze
8790
새 문서: 제목을 잘못만들어서 이 문서를 삭제해야합니다. tipswingspan 문서로 옮겼고 이 문서는 필요없어졌습니다.
wikitext
text/x-wiki
제목을 잘못만들어서 이 문서를 삭제해야합니다.
tipswingspan 문서로 옮겼고 이 문서는 필요없어졌습니다.
90e55d46571fbc5ae7c890511560b0981cffa21a
Tips wingspan
0
247
1452
1451
2023-03-17T12:38:22Z
Tomatocheeze
8790
wikitext
text/x-wiki
==소개==
Wingspan은 핵심적으로 엔진 빌딩 리소스 매니지먼트 게임입니다. 게임에서 가장 제한된 자원은 액션입니다. 각 게임은 26개(8+7+6+5)의 액션으로 제한됩니다. 그러므로 일반적으로 말해, 당신은 모든 액션에서 최대한의 이득을 얻기를 원합니다. 특정 행동(먹이 얻기, 알 낳기, 카드 뽑기)을 취하기 전에 갈색 파워 버드를 플레이하세요. 그러면 그 행동에서 더 많은 것을 얻을 수 있습니다. 핑크 파워 버드를 가능한 한 빨리 플레이하여 여러 번 트리거 될 수 있도록 합니다. 물론, 이에 예외가 있습니다. 예를 들어, 당신이 라운드 종료 목표를 위해 랭킹을 올리는 것이 필요한 경우가 있습니다.
==게임 초반==
게임이 시작될 때, 각 라운드 종료 목표를 분석하는 시간을 가질 필요가 있습니다. 그들은 당신이 어떤 것을 추구해야하는지 크게 결정하기 때문입니다. 알 목표가 많다면, 초원에 더 많은 투자를 하는 것이 좋은 생각일 수 있습니다. 새 목표가 많다면, 숲에 더 많은 투자를 하는 것이 더 나을 수 있습니다. 이 두 가지는 많이 단순화 된 것입니다. 일반적으로 대부분의 게임에서 모든 서식지에서 새를 건설하고 모든 액션을 취할 것입니다. 많은 다른 중요한 고려 사항이 있습니다:
• 세 개 또는 네 개의 둥지 특정 목표는 별 모양 둥지 새가 더 강해지도록합니다.
• 어떤 둥지 목표가 존재하는지 고려하고 해당 둥지 유형의 새를 보유하고 플레이하는 것이 좋습니다.
• 위치 기반 목표 (특정 서식지에 알이나 새)는 이동하는 새들(서식지 간 이동하는 새)이 더 강해지도록합니다.
• 위의 모든 것을 고려할 때, 특정 핑크 파워 버드도 강해집니다. 왜냐하면 상대방은 이러한 액션을 취하거나 라운드 종료 목표를 포기해야하기 때문입니다.
• 4인용 게임에서는 마지막 목표가 더 많은 점수를 주기 때문에 더 중요하게 생각하십시오. 첫 번째 또는 두 번째 목표를 건너 뛰어서 마지막 것을 이기기 위한 위치를 잡을 수 있다면 그것은 문제가 되지 않습니다. 2 또는 3 인용 게임에서는 목표가 동등하며, 2 등과 3 등의 상금은 1 등과 동일한 속도로 커집니다.
보너스 카드를 개인적인 종료 게임 목표로 생각해 보십시오. 보너스 카드 중 하나가 마지막 라운드 종료 목표와 일치하는지 고려하여 그 가치를 높일 수 있습니다.
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
라운드 종료 목표와 위의 정보를 트레이에 있는 새와 손으로 상호 참조하십시오. 이상적으로는 처음 몇 번의 턴을 계획하는 것이 좋습니다. 다음과 같은 일반 원칙이 있습니다:
• 갈색과 분홍색 힘을 가진 새들은 그들의 힘을 작동시킬 수 있는 더 많은 시간이 있는 초기 게임에서 이상적입니다. 더 구체적으로, 당신은 추가적인 카드, 음식, 그리고 계란을 생성하는 힘을 원합니다. 그걸 염두에 두고요.
•• 카드: 이것은 가장 중요한 자원입니다. 좋은 카드 엔진을 가지면 자주 플레이하고 싶은 새를 찾으면서 턱 포인트를 얻을 수 있습니다.
•• 식량: 여러분은 좋은 카드를 찾고 음식을 위해 버려야 할 카드를 찾기 전에는 어떤 음식이 필요한지 모릅니다. 게임 진행 중에는 음식보다 훨씬 많은 카드를 뽑아(버리며)야 합니다. 선택이 가능하다면, 식량을 캐싱하는 것은 대부분 나중에 마지막 몇 턴에 남아있는 조류와 식량 양에 따라 항상 더 나쁩니다.
•• 알: 다른 자원들과 비교했을 때, 알은 게임의 끝까지 가치가 덜하지만, 카드와 음식은 그렇지 않습니다. 그러나, 알을 얻는 방법은 다른 자원과는 다릅니다. 알을 얻을 때는 다른 자원보다 하나 더 많이 받게 되는데, 이를 고려해서 게임 초반에는 알을 사용해 카드를 뽑는 것이 좋습니다. 게임 후반에는 상황에 따라 생각해야 합니다.
• 시작할 떼 가장 좋은 새들은 음식이나 카드를 주는 것입니다. 둘 다 얻으면, 초기 게임이 매우 원활하게 진행됩니다. 물론 이 결정을 내릴 때 각 새의 비용을 고려해야 합니다. 3원 비용의 음식 생산자는 초기에 좋을 수 있지만, 다른 새들을 플레이하는 능력에 어떤 영향을 미칠지 고려해야 합니다.
• 만약 선공을 하는 경우에는, 보이는 새들 중에서 선택할 수 있기 때문에 손에 있는 새들보다 시작하기에 더 좋은 새를 얻을 수 있습니다. 첫 턴에 강력한 새를 뽑는 것도 문제가 되지 않습니다.
• 시작할 때, 보통 손에 있는 새들 중 하나에서 세 마리까지 보유하면 됩니다. 다섯 마리를 보유하는 것은 절대로 하면 안되며, 네 마리를 보유하는 것은 손이 매우 좋거나 비용이 한 개인 숲 조류 카드가 있고 두 번째 턴에 두 개의 식량을 모으기 위해 버릴 계획이 있다면 합리적입니다.
• 상대방이 당신과 동등하게 혜택을 누리는 행동에 대해서는 조심해야 합니다. 이러한 행동들은 아마도 좋지 않을 가능성이 높습니다.
==게임 중반==
중반에는 적어도 하나 이상의 목표에 부합하는 조류들을 가지고 작은 자원 엔진을 갖추고 있어야 합니다. 이 단계에서는 다음과 같은 원칙을 따라야 합니다:
• 상대방의 게임판을 정기적으로 체크하고 어떤 목표를 실현할 수 있는 가능성이 있는지 고려합니다. 어떤 목표를 달성하기 위해 투자해야 할 노력과 그것을 이길 가능성, 그리고 더 큰 장기적 이득을 가져올 수 있는 다른 영역과 비교합니다.
•• 상대방의 자원 수와 엔진 파워도 체크해야 합니다. 그렇게 뒤쳐지지 않았다면, 그들의 자원이 자신보다 많이 증가할 가능성이 낮을 수도 있습니다.
• 핑크색 조류도 체크해야 합니다. 경우에 따라 상대방이 보다 가치 있는 자원을 얻지 못하도록 하기 위해 (알이나 포식자) 행동을 건너뛰는 것이 좋을 수도 있습니다. (얻은 식량이 일반적으로 1점보다 더 가치가 있으므로) 하지만 이것은 고려해야 할 하나의 요소일 뿐입니다. 때로는 상대방을 돕는 행동을 피할 수 없지만, 다른 플레이어와 같은 턴에 그것을 수행할 수 있습니다.
• 중반에는 보너스 카드 조류를 플레이하는 것이 좋습니다. 이렇게 하면 목표에 대한 플레이를 할 시간을 더 가질 수 있습니다. 그러나 카드를 너무 일찍 사용하면 그것이 행동이 없다는 점이 당신에게 해를 끼칠 수 있습니다.
• 좋은 카드 뽑기 엔진이 있다면, 우선순위를 정하고 추가적인 조류를 획득해야 합니다. 마지막 라운드에서 큰 조류 체인을 기반으로 계획을 세울 경우 게임의 흐름을 뒤집을 수 있습니다.
==엔드 게임==
3라운드가 끝나고 최종 라운드가 다가오면 남은 턴을 계획할 수 있어야 합니다. 어떤 목표에 집중해야 할지 최종적인 결정을 내리고 그에 따라 플레이하세요. 가장 높은 등급의 목표를 항상 달성하지 못해도 괜찮습니다. 손에 있는 비목표 새를 플레이하면 더 많은 점수를 얻을 수 있을 수도 있습니다. 새를 플레이하기 위해 음식을 수집하는 각 라운드마다 다른 방법으로 점수를 얻는 기회를 놓치는 것이므로 남은 새를 알로 채우는 것이 좋을 수도 있습니다. 어떤 계획이 가장 많은 점수를 제공하는지 계산할 수 있어야 합니다. 행운을 빕니다!
ea642ac7955759209b6ebcedf118dcdb53f64993
Gamehelpbang
0
199
1453
1436
2023-03-21T09:03:27Z
Junseok
8819
wikitext
text/x-wiki
역할
보안관, 부관, 무법자, 배신자 4개의 직업이 있으며 보안관은 직업을 공개한 채로 시작합니다. 이때 플레이어의 수에 따라
4명 : 1보안관, 2무법자, 1배신자
5명 : 1보안관, 2무법자, 1부관, 1배신자
6명 : 1보안관, 3무법자, 1부관, 1배신자
7명 : 1보안관, 3무법자, 2부관, 1배신자
로 게임이 진행됩니다.
승리 조건
보안관 : 무법자와 배신자를 모두 처치하면 승리
부 관 : 보완관을 지키면 승리
무법자 : 보안관을 처치하면 승리
배신자 : 홀로 살아남으면 승리 (단, 무법자 혹은 부관이 생존했을때 보안관이 죽으면 무법자의 승리)
게임 시작
게임은 보안관부터 시작합니다.(카드 2장을 뽑기 전에 생명력만큼 카드를 가져옵니다.)
자신의 차례가 시작될 때 카드를 2장 뽑습니다. 이후 카드를 원하는 만큼 사용합니다. (단, 뱅! 은 한 턴에 한번만 사용할 수 있습니다)
차례를 마칠 때, 자신의 생명력 만큼 카드를 들고 있을 수 있으며 이외의 카드들은 버려야 합니다.
9e18167a8fb656cff90665e9aa25dedfca154778
1464
1453
2023-04-14T16:13:54Z
Spehs
8849
오타 수정
wikitext
text/x-wiki
역할
보안관, 부관, 무법자, 배신자 4개의 직업이 있으며 보안관은 직업을 공개한 채로 시작합니다. 이때 플레이어의 수에 따라
4명 : 1보안관, 2무법자, 1배신자
5명 : 1보안관, 2무법자, 1부관, 1배신자
6명 : 1보안관, 3무법자, 1부관, 1배신자
7명 : 1보안관, 3무법자, 2부관, 1배신자
로 게임이 진행됩니다.
승리 조건
보안관 : 무법자와 배신자를 모두 처치하면 승리
부 관 : 보안관을 지키면 승리
무법자 : 보안관을 처치하면 승리
배신자 : 홀로 살아남으면 승리 (단, 무법자 혹은 부관이 생존했을 때 보안관이 죽으면 무법자의 승리)
게임 시작
게임은 보안관부터 시작합니다.(카드 2장을 뽑기 전에 생명력만큼 카드를 가져옵니다.)
자신의 차례가 시작될 때 카드를 2장 뽑습니다. 이후 카드를 원하는 만큼 사용합니다. (단, 뱅! 은 한 턴에 한번만 사용할 수 있습니다)
차례를 마칠 때, 자신의 생명력 만큼 카드를 들고 있을 수 있으며 이외의 카드들은 버려야 합니다.
3c4a93d2e791e6f1d40cc04be159925f8e2ffced
1472
1464
2023-06-27T02:53:46Z
XI XVI
9021
wikitext
text/x-wiki
역할
보안관, 부관, 무법자, 배신자 4개의 직업이 있으며 보안관은 직업을 공개한 채로 시작합니다. 이때 플레이어의 수에 따라
4명 : 1보안관, 2무법자, 1배신자
5명 : 1보안관, 2무법자, 1부관, 1배신자
6명 : 1보안관, 3무법자, 1부관, 1배신자
7명 : 1보안관, 3무법자, 2부관, 1배신자
로 게임이 진행됩니다.
승리 조건
보안관 : 무법자와 배신자를 모두 처치하면 승리
부 관 : 보안관을 지키면 승리
무법자 : 보안관을 처치하면 승리
배신자 : 홀로 살아남으면 승리 (단, 무법자 혹은 부관이 생존했을 때 보안관이 죽으면 무법자의 승리)
게임 시작
게임은 보안관부터 시작합니다.(카드 2장을 뽑기 전에 생명력만큼 카드를 가져옵니다.)
자신의 차례가 시작될 때 카드를 2장 뽑습니다. 이후 카드를 원하는 만큼 사용합니다. (단, 뱅! 은 한 턴에 한번만 사용할 수 있습니다)
차례를 마칠 때, 자신의 생명력 만큼 카드를 들고 있을 수 있으며 이 외의 카드들은 버려야 합니다.
52beb344cbf4afd308c4c2646b07021ba4e98f55
Gamehelptrio
0
249
1454
2023-04-08T08:32:34Z
Cust03
8838
Simple translation & context modified.
wikitext
text/x-wiki
테이블에 10/9/8/6장의 카드(각각 2/3/4/5명의 플레이어일 경우)를 뒤집어 놓습니다. 플레이어는 10/8/7/6장의 카드를 받고 핸드는 숫자 순서대로 정렬됩니다.
플레이 방법
자신의 차례에 다음 행동 중 하나를 최대 세 번 수행합니다.
- 테이블 카드 뒤집기
- 손 카드 공개: 아무 플레이어(자신 포함)를 선택하고 핸드의 양쪽 끝에 있는 카드 중 하나를 선택합니다.: 해당 카드는 플레이어 앞에 앞면이 보이도록 놓습니다.
동일한 값을 가진 세 장의 카드를 공개하면 성공한 것입니다.: 이 "트리오" 카드를 점수 세트로 등록합니다.
해당 턴에 이전에 공개한 카드와 일치하지 않는 카드를 공개하면 실패하고 턴이 즉시 종료됩니다. 공개된 카드는 이전 위치와 상태로 돌아갑니다.
승리 조건
순한맛 모드: 3개의 트리오 또는 3개의 7을 사용하면 승리합니다.
매운맛 모드: 두 개의 "연결된" 트리오(한 트리오의 카드에 다른 카드의 작은 아이콘이 포함됨) 또는 세 개의 7 트리오를 가져가면 승리합니다.
참고: 한 쌍의 숫자가 7만큼 다르거나(예: 3과 10) 더하면 7이 됩니다(예: 2와 5).
bbf191e323a9c55f8d733ff636e98ed3b92a6c90
Gamehelpearth
0
250
1455
2023-04-11T00:43:02Z
Kihong
8845
새 문서: 개요 어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다. 설정 게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및...
wikitext
text/x-wiki
개요
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
턴 개요
플레이어의 차례에는 주요 액션을 선택해야 합니다: 심기(초록), 퇴비(빨강), 물(파랑) 또는 성장(노랑). 활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어는 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어는 주 액션 색상과 일치하는 능력이 있는 카드를 활성화할 수 있습니다.
주요 활동
■ 심기(그린): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 심고 다른 플레이어는 1장의 카드를 심습니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 심는 것은 취소할 수 없습니다. 다른 플레이어의 경우 심기는 취소할 수 없습니다)
■ 퇴비 (레드): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
■ 물 (블루): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
■ 성장 (옐로): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
활성화
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드를 활성화합니다. 섬, 기후 그리고 테이블을 활성화하거나 테이블을 활성화한 다음 섬과 기후를 활성화합니다. 테이블을 활성화할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 활성화합니다. 활성화 능력을 건너뛸 수 있습니다. 콜론(:)이 있는 능력의 경우 혜택을 얻으려면 비용을 지불해야 합니다.
검은색 능력은 카드가 테이블에 심어질 때 활성화됩니다. 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 줄입니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불합니다.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑습니다(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
이벤트 카드
이벤트 카드는 행동이나 능력의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 음수 점수를 가지며 게임이 끝날 때 플레이어가 점수를 감소시킵니다.
변환
행동이나 능력의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다(반대는 불가능). 새싹 3개는 게임 종료 시 3점입니다.
동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 카드들은 완료해야 할 게임 내 목표입니다. 목표를 완료한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 다음 플레이어가 턴 순서대로 배치됩니다.
4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 양수와 음수 점수
- 퇴비에서 카드당 1점 획득
- 테이블의 카드에 있는 싹 조각당 1점 획득
- 테이블의 카드에 있는 성장 조각당 1점 획득. 카드 성장 높이가 최대치 (캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
표준 모드는 위의 설명과 같습니다.
고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
e43697cfa2640774f57209ce55aad01bc983246f
1456
1455
2023-04-11T00:47:06Z
Kihong
8845
wikitext
text/x-wiki
※ 개요
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
※ 설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
※ 턴 개요
플레이어의 차례에는 주요 액션을 선택해야 합니다: 심기(초록), 퇴비(빨강), 물(파랑) 또는 성장(노랑). 활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어는 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어는 주 액션 색상과 일치하는 능력이 있는 카드를 활성화할 수 있습니다.
※ 주요 활동
■ 심기(그린): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 심고 다른 플레이어는 1장의 카드를 심습니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 심는 것은 취소할 수 없습니다. 다른 플레이어의 경우 심기는 취소할 수 없습니다)
■ 퇴비 (레드): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
■ 물 (블루): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
■ 성장 (옐로): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
활성화
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드를 활성화합니다. 섬, 기후 그리고 테이블을 활성화하거나 테이블을 활성화한 다음 섬과 기후를 활성화합니다. 테이블을 활성화할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 활성화합니다. 활성화 능력을 건너뛸 수 있습니다. 콜론(:)이 있는 능력의 경우 혜택을 얻으려면 비용을 지불해야 합니다.
검은색 능력은 카드가 테이블에 심어질 때 활성화됩니다. 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 줄입니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불합니다.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑습니다(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
이벤트 카드
이벤트 카드는 행동이나 능력의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 음수 점수를 가지며 게임이 끝날 때 플레이어가 점수를 감소시킵니다.
변환
행동이나 능력의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다(반대는 불가능). 새싹 3개는 게임 종료 시 3점입니다.
동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 카드들은 완료해야 할 게임 내 목표입니다. 목표를 완료한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 다음 플레이어가 턴 순서대로 배치됩니다.
4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 양수와 음수 점수
- 퇴비에서 카드당 1점 획득
- 테이블의 카드에 있는 싹 조각당 1점 획득
- 테이블의 카드에 있는 성장 조각당 1점 획득. 카드 성장 높이가 최대치 (캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
표준 모드는 위의 설명과 같습니다.
고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
cd47c7355b9508a16e701e0e6a272878a52e75f9
1457
1456
2023-04-11T00:48:18Z
Kihong
8845
wikitext
text/x-wiki
※ 개요
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
※ 설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
※ 턴 개요
플레이어의 차례에는 주요 액션을 선택해야 합니다: 심기(초록), 퇴비(빨강), 물(파랑) 또는 성장(노랑). 활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어는 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어는 주 액션 색상과 일치하는 능력이 있는 카드를 활성화할 수 있습니다.
※ 주요 활동
■ 심기(그린): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 심고 다른 플레이어는 1장의 카드를 심습니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 심는 것은 취소할 수 없습니다. 다른 플레이어의 경우 심기는 취소할 수 없습니다)
■ 퇴비 (레드): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
■ 물 (블루): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
■ 성장 (옐로): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
※ 활성화
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드를 활성화합니다. 섬, 기후 그리고 테이블을 활성화하거나 테이블을 활성화한 다음 섬과 기후를 활성화합니다. 테이블을 활성화할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 활성화합니다. 활성화 능력을 건너뛸 수 있습니다. 콜론(:)이 있는 능력의 경우 혜택을 얻으려면 비용을 지불해야 합니다.
검은색 능력은 카드가 테이블에 심어질 때 활성화됩니다. 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
※ 능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 줄입니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불합니다.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑습니다(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
※ 이벤트 카드
이벤트 카드는 행동이나 능력의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 음수 점수를 가지며 게임이 끝날 때 플레이어가 점수를 감소시킵니다.
※ 변환
행동이나 능력의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다(반대는 불가능). 새싹 3개는 게임 종료 시 3점입니다.
※ 동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 카드들은 완료해야 할 게임 내 목표입니다. 목표를 완료한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 다음 플레이어가 턴 순서대로 배치됩니다.
※ 4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
※ 생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
※ 식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
※ 게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 양수와 음수 점수
- 퇴비에서 카드당 1점 획득
- 테이블의 카드에 있는 싹 조각당 1점 획득
- 테이블의 카드에 있는 성장 조각당 1점 획득. 카드 성장 높이가 최대치 (캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
※ 초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
※ 표준 모드는 위의 설명과 같습니다.
※ 고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
※ 솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
654ab0084585fa64427d66caa0147b1025c7ff26
1458
1457
2023-04-11T14:12:06Z
Kihong
8845
wikitext
text/x-wiki
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
※ 설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
※ 턴 개요
플레이어의 차례에는 주요 액션을 선택해야 합니다: 심기(초록), 퇴비(빨강), 물(파랑) 또는 성장(노랑). 활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어는 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어는 주 액션 색상과 일치하는 능력이 있는 카드를 활성화할 수 있습니다.
※ 주요 활동
■ 심기(그린): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 심고 다른 플레이어는 1장의 카드를 심습니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 심는 것은 취소할 수 없습니다. 다른 플레이어의 경우 심기는 취소할 수 없습니다)
■ 퇴비 (레드): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
■ 물 (블루): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
■ 성장 (옐로): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
※ 활성화
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드를 활성화합니다. 섬, 기후 그리고 테이블을 활성화하거나 테이블을 활성화한 다음 섬과 기후를 활성화합니다. 테이블을 활성화할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 활성화합니다. 활성화 능력을 건너뛸 수 있습니다. 콜론(:)이 있는 능력의 경우 혜택을 얻으려면 비용을 지불해야 합니다.
검은색 능력은 카드가 테이블에 심어질 때 활성화됩니다. 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
※ 능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 줄입니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불합니다.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑습니다(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
※ 이벤트 카드
이벤트 카드는 행동이나 능력의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 음수 점수를 가지며 게임이 끝날 때 플레이어가 점수를 감소시킵니다.
※ 변환
행동이나 능력의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다(반대는 불가능). 새싹 3개는 게임 종료 시 3점입니다.
※ 동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 카드들은 완료해야 할 게임 내 목표입니다. 목표를 완료한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 다음 플레이어가 턴 순서대로 배치됩니다.
※ 4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
※ 생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
※ 식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
※ 게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 양수와 음수 점수
- 퇴비에서 카드당 1점 획득
- 테이블의 카드에 있는 싹 조각당 1점 획득
- 테이블의 카드에 있는 성장 조각당 1점 획득. 카드 성장 높이가 최대치 (캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
※ 초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
※ 표준 모드는 위의 설명과 같습니다.
※ 고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
※ 솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
3c75ee07f3e8b2bd87c72461ae4a4dc1bd31ddf7
1459
1458
2023-04-11T17:13:09Z
Kihong
8845
wikitext
text/x-wiki
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
※ 설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
※ 턴 개요
플레이어의 차례에는 메인 액션을 선택해야 합니다: 재배(초록색), 퇴비(빨간색), 물(파란색) 또는 성장(노란색).
활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어들은 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어가 주 액션 색상과 일치하는 능력이 있는 카드를 발동할 수 있습니다.
※ 메인 액션
■ 재배(초록색): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 재배하고 다른 플레이어는 1장의 카드를 재배합니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 재배하는 것은 취소할 수 없습니다. 다른 플레이어의 경우 재배는 취소할 수 없습니다)
■ 퇴비 (빨간색): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
■ 물 (파란색): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
■ 성장 (노란색): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
※ 능력 발동
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드의 능력을 발동합니다. 섬, 기후 그리고 테이블을 발동하거나 테이블을 발동한 다음 섬과 기후를 발동합니다. 테이블을 발동할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 발동합니다. 능력 발동을 건너뛸 수 있습니다.
- 콜론(:)이 있는 능력의 경우 발동 하려면 비용을 지불해야 합니다.
- 검은색 능력은 카드가 테이블에 재배될 때 발동됩니다.
- 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
※ 능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 감소시킵니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑기(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
※ 이벤트 카드
이벤트 카드는 액션이나 능력 발동의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 마이너스 점수를 가지며 게임이 끝날 때 플레이어의 점수를 감소시킵니다.
※ 변환
액션이나 능력 발동의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다.(반대는 불가능) 새싹 3개는 게임 종료 시 3점입니다.
※ 동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 동물들은 완수해야 할 게임 내 목표입니다. 목표를 수행한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 후에 다음 플레이어가 턴 순서대로 배치됩니다.
※ 4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
※ 생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
※ 식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
※ 게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 점수 (마이너스 포함)
- 퇴비의 카드당 1점
- 테이블의 카드에 있는 새싹 조각당 1점
- 테이블의 카드에 있는 성장 조각당 1점. 카드 성장 높이가 최대치(캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
※ 초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
※ 표준 모드는 위의 설명과 같습니다.
※ 고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
※ 솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
cc316aaa4c59a939f01e9a176f3a3692c5bd8c98
1460
1459
2023-04-11T17:14:18Z
Kihong
8845
wikitext
text/x-wiki
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
※ 설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
※ 턴 개요
플레이어의 차례에는 메인 액션을 선택해야 합니다: 재배(초록색), 퇴비(빨간색), 물(파란색) 또는 성장(노란색).
활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어들은 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어가 주 액션 색상과 일치하는 능력이 있는 카드를 발동할 수 있습니다.
※ 메인 액션
- 재배(초록색): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 재배하고 다른 플레이어는 1장의 카드를 재배합니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 재배하는 것은 취소할 수 없습니다. 다른 플레이어의 경우 재배는 취소할 수 없습니다)
- 퇴비 (빨간색): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
- 물 (파란색): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
- 성장 (노란색): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
※ 능력 발동
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드의 능력을 발동합니다. 섬, 기후 그리고 테이블을 발동하거나 테이블을 발동한 다음 섬과 기후를 발동합니다. 테이블을 발동할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 발동합니다. 능력 발동을 건너뛸 수 있습니다.
- 콜론(:)이 있는 능력의 경우 발동 하려면 비용을 지불해야 합니다.
- 검은색 능력은 카드가 테이블에 재배될 때 발동됩니다.
- 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
※ 능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 감소시킵니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑기(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
※ 이벤트 카드
이벤트 카드는 액션이나 능력 발동의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 마이너스 점수를 가지며 게임이 끝날 때 플레이어의 점수를 감소시킵니다.
※ 변환
※ 변환
액션이나 능력 발동의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다.(반대는 불가능) 새싹 3개는 게임 종료 시 3점입니다.
※ 동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 동물들은 완수해야 할 게임 내 목표입니다. 목표를 수행한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 후에 다음 플레이어가 턴 순서대로 배치됩니다.
※ 4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
※ 생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
※ 식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
※ 게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 점수 (마이너스 포함)
- 퇴비의 카드당 1점
- 테이블의 카드에 있는 새싹 조각당 1점
- 테이블의 카드에 있는 성장 조각당 1점. 카드 성장 높이가 최대치(캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
※ 초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
※ 표준 모드는 위의 설명과 같습니다.
※ 고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
※ 솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
6570544e27d7b1821f5c15684a14be964adb06d9
1461
1460
2023-04-11T17:15:38Z
Kihong
8845
wikitext
text/x-wiki
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
※ 설정
※ 설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
※ 턴 개요
플레이어의 차례에는 메인 액션을 선택해야 합니다: 재배(초록색), 퇴비(빨간색), 물(파란색) 또는 성장(노란색).
활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어들은 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어가 주 액션 색상과 일치하는 능력이 있는 카드를 발동할 수 있습니다.
※ 메인 액션
- 재배(초록색): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 재배하고 다른 플레이어는 1장의 카드를 재배합니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 재배하는 것은 취소할 수 없습니다. 다른 플레이어의 경우 재배는 취소할 수 없습니다)
- 퇴비 (빨간색): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
- 물 (파란색): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
- 성장 (노란색): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
※ 능력 발동
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드의 능력을 발동합니다. 섬, 기후 그리고 테이블을 발동하거나 테이블을 발동한 다음 섬과 기후를 발동합니다. 테이블을 발동할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 발동합니다. 능력 발동을 건너뛸 수 있습니다.
- 콜론(:)이 있는 능력의 경우 발동 하려면 비용을 지불해야 합니다.
- 검은색 능력은 카드가 테이블에 재배될 때 발동됩니다.
- 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
※ 능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 감소시킵니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑기(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
※ 이벤트 카드
이벤트 카드는 액션이나 능력 발동의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 마이너스 점수를 가지며 게임이 끝날 때 플레이어의 점수를 감소시킵니다.
※ 변환
※ 변환
※ 변환
액션이나 능력 발동의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다.(반대는 불가능) 새싹 3개는 게임 종료 시 3점입니다.
※ 동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 동물들은 완수해야 할 게임 내 목표입니다. 목표를 수행한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 후에 다음 플레이어가 턴 순서대로 배치됩니다.
※ 4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
※ 생태계 카드
※ 생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
※ 식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
※ 게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 점수 (마이너스 포함)
- 퇴비의 카드당 1점
- 테이블의 카드에 있는 새싹 조각당 1점
- 테이블의 카드에 있는 성장 조각당 1점. 카드 성장 높이가 최대치(캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
- 초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
- 표준 모드는 위의 설명과 같습니다.
- 고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
- 솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
11d5ccc0a0e4cfc2f27e09706be912bb9bcb3230
1462
1461
2023-04-11T17:20:08Z
Kihong
8845
wikitext
text/x-wiki
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
※ 설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
※ 턴 개요
플레이어의 차례에는 메인 액션을 선택해야 합니다: 재배(초록색), 퇴비(빨간색), 물(파란색) 또는 성장(노란색).
활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어들은 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어가 주 액션 색상과 일치하는 능력이 있는 카드를 발동할 수 있습니다.
※ 메인 액션
- 재배(초록색): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 재배하고 다른 플레이어는 1장의 카드를 재배합니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 재배하는 것은 취소할 수 없습니다. 다른 플레이어의 경우 재배는 취소할 수 없습니다)
- 퇴비 (빨간색): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
- 물 (파란색): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
- 성장 (노란색): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
※ 능력 발동
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드의 능력을 발동합니다. 섬, 기후 그리고 테이블을 발동하거나 테이블을 발동한 다음 섬과 기후를 발동합니다. 테이블을 발동할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 발동합니다. 능력 발동을 건너뛸 수 있습니다.
- 콜론(:)이 있는 능력의 경우 발동 하려면 비용을 지불해야 합니다.
- 검은색 능력은 카드가 테이블에 재배될 때 발동됩니다.
- 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
※ 능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 감소시킵니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑기(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
※ 이벤트 카드
이벤트 카드는 액션이나 능력 발동의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 마이너스 점수를 가지며 게임이 끝날 때 플레이어의 점수를 감소시킵니다.
※ 변환
액션이나 능력 발동의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다.(반대는 불가능) 새싹 3개는 게임 종료 시 3점입니다.
※ 동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 동물들은 완수해야 할 게임 내 목표입니다. 목표를 수행한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 후에 다음 플레이어가 턴 순서대로 배치됩니다.
※ 4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
※ 생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
※ 식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
※ 게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 점수 (마이너스 포함)
- 퇴비의 카드당 1점
- 테이블의 카드에 있는 새싹 조각당 1점
- 테이블의 카드에 있는 성장 조각당 1점. 카드 성장 높이가 최대치(캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
- 초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
- 표준 모드는 위의 설명과 같습니다.
- 고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
- 솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
106c829e4c055cd1456b11d4849efccbc887e453
1463
1462
2023-04-11T17:20:53Z
Kihong
8845
wikitext
text/x-wiki
어스(Earth)는 각 플레이어가 차례대로 지형과 식물로 자신의 섬을 만드는 라운드를 통해 진행되는 엔진 빌딩 게임입니다. 게임은 한 플레이어가 4x4 테이블을 16장의 카드로 구성하여, 섬을 완성한 라운드가 끝날 때 종료됩니다.
※ 설정
게임은 각 플레이어가 섬, 기후 및 생태계 카드를 선택하는 것으로 시작됩니다. 섬 카드는 플레이어가 시작할 때 , 퇴비 크기 및 카드 패를 결정합니다. 기후 카드는 초기 엔진에 도움이 되는 기본 능력을 가지고 있습니다. 생태계 카드는 게임 종료 시점에 점수를 매기는 카드입니다.
※ 턴 개요
플레이어의 차례에는 메인 액션을 선택해야 합니다: 재배(초록색), 퇴비(빨간색), 물(파란색) 또는 성장(노란색).
활성 플레이어는 더 강력한 액션을 수행하고 다른 플레이어들은 덜 강력한 액션을 수행합니다. 그런 다음 모든 플레이어가 주 액션 색상과 일치하는 능력이 있는 카드를 발동할 수 있습니다.
※ 메인 액션
- 재배(초록색): 패에서 카드를 꺼내 테이블에 놓습니다. 카드 비용을 으로 지불해야 합니다. 게임이 끝날 때까지 카드를 4x4 테이블에 채워야 합니다. 카드를 배치할 때 기존 테이블의 카드와 대각선 또는 직선으로 붙어 있어야 합니다. 활성 플레이어는 2장의 카드를 재배하고 다른 플레이어는 1장의 카드를 재배합니다. 그 후 활성 플레이어는 4장의 카드를 뽑아 1장을 유지하고 다른 플레이어는 1장의 카드를 뽑습니다. (카드를 뽑는 것은 취소할 수 없으므로 활성 플레이어의 경우 두 번째 카드를 재배하는 것은 취소할 수 없습니다. 다른 플레이어의 경우 재배는 취소할 수 없습니다)
- 퇴비 (빨간색): 토양을 얻거나 덱에서 카드를 뽑아서 보지 않고 퇴비에 넣습니다. 퇴비에 있는 각 카드는 게임이 끝날 때 1점을 얻습니다.
- 물 (파란색): 테이블에 있는 카드의 싹 위치에 싹(큐브)을 놓거나 토양을 얻습니다. 각 싹은 게임이 끝날 때 1점을 얻습니다.
- 성장 (노란색): 테이블에 있는 카드의 성장 위치에 성장 조각이나 천막을 놓고/또는 패로 카드를 뽑습니다. 각 성장 조각은 게임이 끝날 때 1점을 얻지만, 카드의 최대 성장에 도달했을 때 마지막으로 놓는 조각은 천막이어야 합니다. 천막이 있는 카드는 조각당 1점 대신 카드에 표시된 성장 점수를 얻습니다. (카드를 뽑는 것은 취소할 수 없습니다.)
※ 능력 발동
메인 액션 이후 모든 플레이어는 일치하는 색상의 카드의 능력을 발동합니다. 섬, 기후 그리고 테이블을 발동하거나 테이블을 발동한 다음 섬과 기후를 발동합니다. 테이블을 발동할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순서대로 발동합니다. 능력 발동을 건너뛸 수 있습니다.
- 콜론(:)이 있는 능력의 경우 발동 하려면 비용을 지불해야 합니다.
- 검은색 능력은 카드가 테이블에 재배될 때 발동됩니다.
- 갈색 능력은 게임 내 효과이거나 게임 종료 시 점수입니다.
※ 능력
게임 내에서 일반적인 능력들:
- 덱에서 카드 뽑기(취소할 수 없음)
- 성장 조각 획득 또는 지불
- 새싹 조각 획득 또는 지불
- 토양 획득 또는 지불
- 손에서 카드를 퇴비화
- 덱의 카드를 퇴비화 (취소할 수 없음)
- 퇴비에서 카드 버리기(취소할 수 없음)
- 특정 유형(나무, 허브, 버섯, 덤불) 또는 특정 서식지(햇볕, 습지, 바위, 한랭)의 카드 비용을 감소시킵니다.
게임 내에서 희귀한 능력들:
- 퇴비에서 카드 뽑기(취소할 수 없음)
- 퇴비, 새싹 조각 또는 성장 조각으로 카드 비용의 일부를 지불.
- 다른 카드의 능력 복사
- 비용 없이 다른 카드를 심고 카드를 뽑기(취소할 수 없음).
- 플레이어가 특정 주요 작업을 선택하지 못하도록 방지
- 모든 유형으로 간주되는 카드(나무, 허브, 버섯, 덤불)
※ 이벤트 카드
이벤트 카드는 액션이나 능력 발동의 중간을 제외하고 언제든지 사용할 수 있습니다. 사용된 이벤트 카드는 플레이어 보드의 더미에 배치됩니다. 일부 이벤트 카드는 마이너스 점수를 가지며 게임이 끝날 때 플레이어의 점수를 감소시킵니다.
※ 변환
액션이나 능력 발동의 중간을 제외하고 언제든지 플레이어는 3개의 새싹을 2개의 토양으로 전환할 수 있습니다.(반대는 불가능) 새싹 3개는 게임 종료 시 3점입니다.
※ 동물 카드
게임 시작 시 4개의 동물 카드가 무작위로 선택됩니다. 이 동물들은 완수해야 할 게임 내 목표입니다. 목표를 수행한 첫 번째 플레이어는 더 많은 점수를 얻습니다. 여러 플레이어가 같은 턴에 목표를 완료하면 활성 플레이어가 더 많은 점수를 얻은 후에 다음 플레이어가 턴 순서대로 배치됩니다.
※ 4x4 테이블 보너스
테이블의 4x4 칸을 전부 완성한 첫 번째 플레이어는 7점의 보너스를 얻습니다. 여러 플레이어가 같은 턴에 테이블을 완료하면 활성 플레이어가 보너스를 얻거나 턴 순서의 첫 번째 플레이어가 점수를 얻습니다.
※ 생태계 카드
각 플레이어는 생태계 카드를 가지고 있으며, 무작위로 선택된 2장의 공용 생태계 카드가 있습니다. 플레이어의 생태계 카드는 소유한 플레이어만 점수를 얻을 수 있습니다. 공용 생태계 카드는 모든 플레이어가 점수를 얻습니다.
※ 식물 vs 카드
동물이나 생태계 카드에서 표기된 식물은 테이블의 심은 그린 카드(나무, 허브, 버섯, 덤불)에만 적용된다는 것을 의미합니다. 카드가 표기되어 있다면 테이블의 모든 카드와 섬, 기후 카드를 의미합니다.
※ 게임 종료 시 점수
게임이 끝날 때 점수 계산:
- 테이블, 섬 및 기후 카드의 기록된 점수
- 이벤트 카드에서 얻은 점수 (마이너스 포함)
- 퇴비의 카드당 1점
- 테이블의 카드에 있는 새싹 조각당 1점
- 테이블의 카드에 있는 성장 조각당 1점. 카드 성장 높이가 최대치(캐노피가 있음)인 경우, 카드에 있는 점수를 대신 얻음
- 점수를 얻는 갈색 능력이 있는 테이블의 지형 카드 점수 획득
- 개인 생태계 카드 점수 획득
- 2장의 공용 생태계 카드 점수 획득
- 동물 보드에서 점수 획득: 4장의 카드와 4x4 테이블을 가장 먼저 완성한 플레이어에게 주어지는 보너스 포함
- 초보자 모드에는 생태계 카드가 없습니다. 또한 모든 플레이어는 동물 카드 목표당 10점을 얻습니다.
- 표준 모드는 위의 설명과 같습니다.
- 고급 모드에서 플레이어는 게임 시작 시 더 많은 섬, 기후 및 생태계 카드를 선택할 수 있지만 게임 플레이는 표준 모드와 동일합니다.
- 솔로 모드에서는 가이아와 대결합니다. 플레이어는 평소와 같이 턴을 진행하고, 가이아는 플레이어의 주요 행동을 따릅니다. 그런 다음 가이아는 6장의 가이아 카드 덱에서 카드를 뽑아 턴을 진행합니다. 플레이어는 가이아의 행동을 따르고, 가이아는 주요 행동을 진행합니다. 6장의 카드가 모두 뽑히면, 덱이 다시 섞이고 다음 6턴을 진행합니다. 플레이어가 4x4 테이블을 완성하거나 가이아가 마지막 카드를 뽑을 때 게임이 끝납니다.
ec51167f47982c616c46e54acdcc2d0b6ca820c3
Gamehelpstirfryeighteen
0
251
1465
2023-04-19T03:54:18Z
Ddukk
8853
새 문서: 셰프 여러분 환영합니다!<br><br> Stir Fry Eighteen은 상대방을 속이고 테이블에서 가장 많은 점수를 얻으려고 노력하면서 볶음 국수 요리를 하는 게임입니다.<br><br> 플레이어는 매 턴마다 "같은 재료 두 장" 또는 "단백질이 포함된 재료 (새우, 돼지고기 또는 치킨)"를 뒤집어서 버리고 추가 카드를 드로우 할 수 있습니다.<br> 각 플레이어는 자기 차례가 되면 카드를 한 장...
wikitext
text/x-wiki
셰프 여러분 환영합니다!<br><br>
Stir Fry Eighteen은 상대방을 속이고 테이블에서 가장 많은 점수를 얻으려고 노력하면서 볶음 국수 요리를 하는 게임입니다.<br><br>
플레이어는 매 턴마다 "같은 재료 두 장" 또는 "단백질이 포함된 재료 (새우, 돼지고기 또는 치킨)"를 뒤집어서 버리고 추가 카드를 드로우 할 수 있습니다.<br>
각 플레이어는 자기 차례가 되면 카드를 한 장 드로우하며, 재료 카드들을 뒤집어서 버리고 더 많은 카드를 뽑을 수 있습니다.<br>
동료 셰프들은 뒤집어서 버린 재료에 대해 맛 테스트를 요청하고 확인할 수 있습니다! 거짓 재료를 사용하는 다른 셰프를 적발하는 일은 매우 즐겁고 추가 카드도 받을 수 있지만, 셰프를 잘못 고발하면 손에 있는 모든 카드를 잃게 되니 주의하세요!<br><br>
Stir Fry Eighteen은 아래 규칙에서 #SF18로도 표기되어 있습니다.<br><br><br>
카드의 종류 및 가치<br><br>
총 18장의 카드로 구성되어 있습니다:<br><br>
1 - 새우 (6점, 생강과 함께 요리하면 9점, 간장 및 생강과 함께 요리하면 11점, 버리고 카드 4장 드로우)<br>
1 - 돼지고기 (5점, 버섯과 함께 요리하면 8점, 버리고 카드 3장 드로우)<br>
1 - 치킨 (3점, 대파와 함께 요리하면 5점, 생강 및 대파와 함께 요리하면 7점, 버리고 카드 2장 드로우)<br>
2 - 생강 (2점, 돼지고기와 함께 요리하면 4점)<br>
2 - 대파 (3점, 새우와 함께 요리하면 5점)<br>
3 - 간장 (1점, 대파와 함께 요리하면 2점, 생강과 함께 요리하면 3점)<br>
3 - 버섯 (2점, 치킨과 함께 요리하면 3점)<br>
5 - 국수 (1점)<br><br><br>
게임 방법<br><br>
- #SF18 덱을 섞고 각 셰프에게 3장의 카드를 나누어 줍니다.<br>
- 가장 최근에 볶음밥을 먹은 셰프가 먼저 진행합니다!<br>
- 턴을 시작할 때 덱에서 카드를 드로우합니다.<br>
- 당신의 차례나 다른 요리사의 차례에 각자 핸드에 소지할 수 있는 카드 수에는 제한이 없습니다.<br>
- 턴 종료 시 카드를 3장까지만 남기고 모두 버려야 합니다.<br>
- 다음 내용에 플레이어가 취할 수 있는 행동, 요리 지침, 차례를 끝내는 방법, 동료 셰프를 속이거나 맛 테스트를 요청하는 모든 것이 포함되어 있습니다!<br><br><br>
셰프의 행동<br><br>
새 카드를 뽑기 위해 버리기:<br><br>
- 버리는 것은 뒤집어서 하고, 속임수를 권장합니다.<br>
- "일치하는 한 쌍의 재료" 카드들을 버리고 3장의 카드를 뽑습니다. (한 턴에 한 번만 가능) 버리는 쌍의 재료 유형을 말 할 필요는 없습니다.<br>
- "단백질이 포함된 재료 (새우, 돼지고기 또는 치킨)" 카드를 버리고 카드에 적힌 수 만큼 카드를 뽑습니다. (한 턴에 한 번만 가능)<br>
참고 : 턴당 일치하는 한 쌍의 재료 또는 단백질이 포함된 재료 버리기 행동은 각각 한 번만 수행할 수 있지만, 원하는 경우 매 턴마다 두 유형을 모두 수행할 수 있습니다.<br><br>
볶음 요리하기:<br><br>
- 턴당 한 번 3-5가지 다른 재료를 사용하여 요리할 수 있습니다. (3개 이상, 5개 이하).<br>
- 볶음 요리의 재료로 면은 필수로 포함되어야 합니다.<br>
- 한 번의 볶음 요리에 같은 두 재료를 포함할 수 없습니다.<br>
- 덱이 다 떨어지면 요리할 때까지 다시 섞지 않습니다.<br>
- 재료 및 보너스 점수를 세고 합계를 기록합니다. (충족된 보너스중 가장 높은 값만 선택됩니다.)<br><br>
턴 종료:<br><br>
- 사용되거나 폐기된 모든 카드를 모아 덱에 섞습니다.<br>
- 이번 턴에 요리했다면 카드를 한 장 뽑습니다.<br>
- 요리를 할 수 없거나 하기 싫다면 차례를 패스 할 수 있습니다.<br>
- 카드가 3장 이상이면 3장이 되도록 버리고 덱을 다시 섞습니다.<br><br>
블러핑 및 맛 테스트:<br><br>
- 속임수가 권장되지만 동료 셰프가 맛 테스트를 요청할 수도 있습니다!<br>
- 맛 테스트는 셰프가 당신이 버린 것에 대해 거짓말을 했다고 주장하는 것입니다.<br>
- 맛 테스트를 요청한 셰프는 즉시 카드를 뒤집어 확인합니다.<br>
- 버린 카드가 진실인 경우, 맛 테스트를 요청한 셰프는 모든 카드를 즉시 버립니다.<br>
- 맛 테스트를 요청한 셰프가 가지고 있는 카드가 없으면 5점을 대신 잃습니다.<br>
- 빈 손으로 5점 미만이면 맛 테스트를 요청 할 수 없습니다.<br>
- 맛 테스트를 요청한 셰프가 속임수를 적발하면, 다음 턴 시작시 추가 카드를 뽑습니다.<br>
- 셰프가 속임수를 쓰다 걸리면 남은 턴 동안 카드를 뽑을 수 없습니다.<br><br>
예시: Pat은 두 장의 카드를 뒤집어 놓고 세 장의 카드를 뽑으려고 시도합니다. Ralph는 맛 테스트를 요청하고 즉시 버려진 카드를 뒤집어 생강과 대파를 적발합니다. Ralph는 다음 차례를 시작할 때 카드 한 장을 추가로 뽑고 Pat은 아무것도 얻지 못합니다.<br><br>
참고: 이 능력은 부가적입니다. 당신의 다음 턴 전에 2번의 속임수를 성공적으로 마쳤다면, 당신은 다음 턴에 두 장의 추가 카드를 뽑을 것입니다.<br><br><br>
게임 승리<br><br>
50점을 먼저 얻는 셰프가 승리합니다!<br><br><br>
변형<br><br>
위는 기본 승리 조건입니다. 익숙해지면 다음과 같은 약간의 변형 중 하나를 시도하십시오.<br><br>
연장 영업 - 최종점수 계산 규칙 변형입니다. 50점 이상에 도달한 플레이어가 나온 후, 다른 플레이어는 각각 1턴씩 진행할 수 있습니다. 이 턴이 끝날 때 가장 높은 점수를 얻은 플레이어가 승리합니다.<br>
마스터 셰프 - 300점까지 플레이하세요!<br>
식료품 부족 규칙 - 플레이어는 요리한 뒤 카드를 뽑지 않습니다!<br>
정확한 셰프 셰프 변형 규칙 - 플레이어는 승리하려면 정확히 50점을 얻어야 합니다! (PAX South 2016에서 Thomas W.가 자신만의 레시피를 혼합하여 개발했습니다.)<br>
두부 프로모 카드 - 덱 중 한 장이 두부 카드로 바뀌고 무엇이 바뀌었는지는 모릅니다.<br><br>
나만의 레시피를 섞어보세요! - #SF18을 위한 나만의 변형 규칙을 만드셨나요? www.YanaguanaGames.com에서 공유하세요!
b99615f161b27e1c737fcdf79f053d14b46475a0
Gamehelpcoupcitystate
0
252
1466
2023-04-20T12:32:03Z
Gomdol1
8856
게임하는 방법 한국어 번역
wikitext
text/x-wiki
== '''소개''' ==
쿠데타에서 플레이어는 르네상스 이탈리아의 부패한 도시 국가를 장악하기 위해 경쟁합니다. 궁정에서 자신의 영향력(손에 든 캐릭터 카드)을 통해 상대방을 허세 부리고, 훔치고, 살해하여 최후의 생존자가 되어 권력을 잡으세요. 2등은 없습니다.
== '''덱 구성''' ==
덱은 5가지 캐릭터(외교관, 암살자, 사령관, 귀부인, 공작)가 고르게 분포되어 있습니다.
15장 카드 덱에는 각 캐릭터가 3장씩 들어 있습니다.
20장 카드 덱에는 각 캐릭터가 4장씩 들어 있습니다.
덱의 크기는 게임 플레이어 수에 따라 다릅니다.
각 플레이어는 ₤2(2인 게임에서는 ₤1)와 카드 2장으로 시작합니다. 돈은 공개되지만, 손에 든 캐릭터 카드는 비밀입니다.
== '''행동''' ==
자신의 차례가 되면, 감당할 수 있는 행동을 취하세요:
=== '''일반 행동 (항상 사용 가능)''' ===
- 수입: 국고에서 ₤1을 가져옵니다. 방해할 수 없습니다.
- 외국 원조: 국고에서 ₤2를 받습니다. 공작/외교관이라고 주장하는 플레이어는 누구나 방해할 수 있습니다.
- 쿠데타: 7₤을 국고에 지불하고 다른 플레이어의 영향력을 잃게 합니다(캐릭터 카드 한 장을 죽입니다). 막을 수 없습니다. 10₤으로 차례를 시작하면 이 행동을 선택해야 합니다.
=== '''캐릭터 행동(해당 캐릭터 카드를 손에 들고 있다고 주장해야 합니다!)''' ===
- 징세 (공작): 국고에서 ₤3을 가져옵니다. 막을 수 없습니다.
- 강탈 (사령관): 다른 플레이어에게서 ₤2를 훔칩니다. 대상 플레이어는 외교관 또는 사령관이라고 주장하여 막을 수 있습니다.
- 교환 (외교관): 덱에서 카드를 2장 뽑은 다음, 원하는 카드 2장을 덱으로 되돌립니다. 방해할 수 없습니다.
- 암살 (자객): 3₤을 국고에 지불하고 다른 플레이어의 영향력을 잃게 합니다(캐릭터 카드 한 장을 죽입니다). 대상 플레이어는 귀부인을 주장하여 막을 수 있습니다.
== '''도전''' ==
캐릭터를 주장하는 모든 플레이어에게 도전할 수 있습니다. 도전을 받으면 항상 도전자와 도전을 받은 플레이어 중 하나는 캐릭터를 잃게 됩니다. 도전을 받은 플레이어는 자신의 패에서 카드를 공개합니다.
- 주장이 거짓일 경우, 공개한 카드는 죽습니다.
- 진실이라면, 공개된 카드는 덱에 섞여 교체되고, 도전자는 자신의 패에서 카드 한 장을 죽입니다.
죽은 캐릭터 카드는 앞면이 위로 향하게 되며, 그 영향력은 더 이상 사용할 수 없습니다. 두 캐릭터가 모두 죽으면 플레이어는 탈락합니다. 마지막으로 남은 플레이어가 승리합니다!
== '''변형 룰:진영''' ==
이 변형에서는 플레이어가 군주파와 포퓰리스트 두 진영(팀)으로 나뉩니다. 두 진영이 존재하는 한, 플레이어는 팀원을 방해하거나 타겟팅할 수 없습니다(단, 전환과 도전은 항상 허용됩니다). 진영이 하나만 존재하면 내분이 발생하며 아무런 제한이 적용되지 않습니다.
== '''추가 행동''' ==
- 전환: 자신의 진영을 변경하려면 알름하우스에 1파운드를 지불하고, 다른 플레이어의 진영을 변경하려면 알름하우스에 2파운드를 지불합니다. 방해할 수 없습니다.
- 횡령 (공작/외교관을 제외한 모든 캐릭터): 공작/외교관이 아닌 경우 자선냄비에 있는 모든 코인을 가져갑니다. 방해할 수 없습니다.
횡령 행동이 도전을 받으면, 도전을 받은 플레이어는 손에 든 카드를 '''모두''' 공개합니다. 공작/외교관이 공개되면(거짓), 한 장이 죽습니다(공개된 다른 카드는 덱에 섞여 교체됩니다). 그렇지 않은 경우(진실), 두 장의 카드를 모두 덱에 섞어 교체하고, 도전자는 정상적으로 패에서 카드 한 장을 죽입니다.
== '''변형: 인퀴지터''' ==
이 변형은 대사 캐릭터를 종교 재판관으로 대체합니다. 종교 재판관은 여전히 도둑질을 방해하고 두 가지 캐릭터 행동을 할 수 있습니다:
- 교환 (종교 재판관): 법원 덱에서 카드를 1장 뽑은 다음, 1장을 덱으로 되돌린다. 방해할 수 없습니다.
- 조사 (종교 재판관): 다른 플레이어의 패에 있는 카드 1장을 몰래 봅니다. 카드를 소유자에게 돌려줄지, 아니면 소유자가 강제로 코트 덱과 교환하도록 할지를 선택합니다. 귀부인으로 막을 수 있습니다.
== '''변형: 외교관''' ==
이 변형은 공작 캐릭터를 외교관으로 대체합니다. 외교관은 여전히 외국 원조를 방해하고 횡령할 수 없으며, 캐릭터 행동이 하나뿐입니다:
- 협력 (외교관으로서) : 국고에서 ₤3을 가져와 다른 플레이어에게 ₤1을 줍니다. 방해할 수 없습니다.
1295cf1bee0b9064182e223f10cb1c6d7ea71a0c
Gamehelpluckynumbers
0
207
1467
1337
2023-04-26T00:42:19Z
Seongmin2
8871
wikitext
text/x-wiki
행운의 숫자는 행운에 예측을 곁들인 간단한 게임입니다.
==목표==
목표는 격자 판을 16개의 숫자 타일로 모두 채우는 것입니다. 각 행의 숫자들은 왼쪽에서 오른쪽으로 갈수록 커져야 하며, 각 열의 숫자들은 위에서 아래로 갈수록 커져야 합니다. 같은 행이나 같은 열에서 같은 숫자를 두번 사용할 수는 없습니다.
완성된 격자 판의 예시:
[[File:Lucky_numbers2.jpg|Lucky_numbers2.jpg]]
처음으로 격자 판을 채운 플레이어가 승리합니다.
여러 라운드에서의 점수 계산: 승자는 2점을 얻습니다. 다른 플레이어들은 각자의 격자 판에서 빈칸 하나에 1점씩 점수를 잃습니다.
==게임 플레이==
각 플레이어마다, 1~20의 타일을 섞은 뒤, 대각선으로 4개의 숫자를 놓고 시작합니다.
이때 4개의 숫자는 왼쪽상단부터 오른쪽하단으로 오름차순이 되게 놓습니다(숫자가 중복일경우 이어서 놓습니다)
턴이 시작할 때, 더미에서 무작위 타일 하나를 뽑아오거나 (테이블에 타일이 있다면) 타일 하나를 손으로 가져옵니다.
같은 행과 열에서 앞에 있는 타일보다 높은 수이거나, 뒤에 있는 타일보다 낮은 수일 경우 놓을 수 있습니다.<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 테이블에서 타일을 가져올 경우, 반드시 그 타일을 사용해야만 합니다.
격자 판 위의 타일과 교체하거나, 뽑은 타일을 버릴 경우, 그 타일은 테이블에 놓여져 다음 플레이어 차례로 넘어갑니다.
<span style="font-size: 80%; margin-top:100px; margin-bottom:100px; color: blue;">[1]</span> 앞:왼쪽/위, 뒤:오른쪽/아래
791459c7154215c653d57f6db2aa45366609c11d
Gamehelpnextstationtokyo
0
253
1468
2023-05-28T08:48:44Z
Ynomad
8692
새 문서: 목표: 훌륭한 관광 지하철 지도를 만들고 도쿄에서 가장 많은 점수를 획득합니다. Next Station London을 플레이했다면 기본은 같지만 몇 가지 차이점이 있습니다. 플레이 방법 카드 뒤집기 각 회전마다 네 개의 기호 중 하나가 있는 카드가 뒤집힙니다. 모든 플레이어는 보드의 점선 가이드 중 하나를 따라 시작 지점에서 이 기호가 있는 스테이션까지 직선을 그립니다...
wikitext
text/x-wiki
목표: 훌륭한 관광 지하철 지도를 만들고 도쿄에서 가장 많은 점수를 획득합니다. Next Station London을 플레이했다면 기본은 같지만 몇 가지 차이점이 있습니다.
플레이 방법
카드 뒤집기
각 회전마다 네 개의 기호 중 하나가 있는 카드가 뒤집힙니다. 모든 플레이어는 보드의 점선 가이드 중 하나를 따라 시작 지점에서 이 기호가 있는 스테이션까지 직선을 그립니다 와일드(조커) 기호가 뒤집히면 해당 스테이션의 기호를 선택할 수 있으며 플레이어는 동일한 기호를 선택할 필요가 없습니다. 또한 새 지하철 노선을 그리는 것은 항상 선택 사항이며, 원하는 경우 카드 전환을 건너뛸 수 있습니다.
새 라운드 시작
녹색 기호 5개가 모두 뒤집힐 때까지 이 방법을 계속합니다. 이는 각 라운드에 5-10개의 카드가 뒤집힐 것임을 의미합니다. 그런 다음, 다음 선수에게 색깔을 전달하고, 다음 출발점부터 다음 지하철 노선을 시작합니다. 지하철 4호선이 모두 채워질 때까지 계속 가세요.
선 그리기 규칙
지하철 노선들은 그들 자신이나 다른 노선을 건널 수 없다는 것을 명심하세요 -- 이미 지도에 있는 녹색 중앙선을 포함해서. 열차 노선이 같은 역을 다시 방문할 수는 없지만 여러 다른 열차 노선이 같은 역을 방문할 수는 있습니다.
특수 카드
조커 + 더블 레일 트랙
기존 선을 따라 새 선 세그먼트를 계속 진행할 수 있는 유일한 방법은 기존 선이 다른 색상이고 조커 + 더블 레일 트랙 카드가 그려진 경우입니다. 이 경우 기존 선 세그먼트(녹색 트랙의 곡선 세그먼트도)를 한 번에 재사용할 수 있습니다.
선로 전환
일반적으로 새 라인 세그먼트는 항상 트랙의 양쪽 끝에 있는 스테이션에서 계속되어야 합니다. 그러나 Railway Switch(선로 전환) 카드가 그려진 경우, 해당 라운드의 지하철 선로에 있는 모든 역에서 새 라인 세그먼트를 그릴 수 있으며, 향후 라운드에서 사용할 추가적인 종단이 생성될 수 있습니다. (Railway Switch를 먼저 또는 두 번째로 뒤집으면 아무 효과가 없습니다.)
주황색 효과 카드
주황색 효과 카드를 가지고 플레이하는 경우, 그것들은 특정 기호의 첫 번째 뒤집힌 카드에 추가적인 효과를 줍니다. (효과 근처의 파란색 기호로 표시됩니다.)
스코어링
라인 스코어링
각 행은 개별적으로 점수를 매깁니다. 선에 점수를 매기려면 통과하는 구역 수를 계산합니다. (구역은 노란색 선으로 구분된 구역입니다.) 그런 다음 이 값에 특정 구역에서 이 선이 방문한 역의 수를 곱합니다. 즉, 이 선에 대해 가장 많은 역이 있는 구역입니다. 예를 들어, 한 선이 5개 구역을 방문하고 한 구역에 3개 역을 방문하면 해당 선의 점수는 5 x 3 = 15점입니다. 그런 다음 서로 다른 선에 대해 동일한 과정을 반복하고 이 선 점수를 함께 추가합니다.
인터체인지 및 관광지 인지 채점
인터체인지는 기존 녹색 선을 포함하여 둘 이상의 색상 선이 방문하는 측점입니다. 3개의 선, 4개의 선 또는 5개의 선이 교대할 때 각각 5, 15 또는 30점의 점수를 받습니다.
지도 가장자리에 닿는 각 영역은 적어도 하나의 교환이 있을 경우 점수를 매깁니다. 네 개의 코너 영역은 각각 10점을 받고, 나머지 네 개의 영역은 각각 5점을 받습니다. (점수 패드의 중간 하단에 있는 파란색 상자 아래에 점수가 매겨집니다.)
녹색 선로 미연결 점수(벌점)
다른 연결선이 없는 녹색 선에서 플레이어는 각 스테이션에 대해 3점을 잃습니다.
목표
목표를 가지고 경기할 경우, 각 선수는 완료한 목표당 10점을 득점합니다.
5b6b40d5b2792312c8a8eaabf9b4e1cc3c24915a
Gamehelpchallengers
0
254
1469
2023-06-06T02:40:31Z
Kimbob128
8968
새 문서: 요약 플레이어는 7라운드 동안 드래프트("덱 단계") 및 카드 공개("매치 단계") 단계에 참여합니다. 이후 3~8인 게임의 경우 7라운드를 모두 마친 후 가장 많은 팬을 보유한 2명의 플레이어만이 결승전에 진출할 수 있습니다. 1~2인의 경우 결승전이 없으며 가장 많은 팬을 모은 플레이어가 승리합니다. 1~2인 플레이어의 경우 플레이어가 매치 페이즈 후 최소 11명의 팬...
wikitext
text/x-wiki
요약
플레이어는 7라운드 동안 드래프트("덱 단계") 및 카드 공개("매치 단계") 단계에 참여합니다.
이후 3~8인 게임의 경우 7라운드를 모두 마친 후 가장 많은 팬을 보유한 2명의 플레이어만이 결승전에 진출할 수 있습니다.
1~2인의 경우 결승전이 없으며 가장 많은 팬을 모은 플레이어가 승리합니다. 1~2인 플레이어의 경우 플레이어가 매치 페이즈 후 최소 11명의 팬을 모으면 즉시 승리합니다.
카드종류
각 카드의 상단 모서리에는 기본 능력이 표시되고 상단에는 카드 세트 아이콘이 표시됩니다. 카드의 오른쪽 하단에는 레벨을 설명하는 문자도 있습니다.
*S = 스타터 카드
*A = 저레벨 카드, 최대 1~3 기본 전력
*B = 중급레벨의 카드, 최대 1~5 기본 전력
*C = 높은 수준레벨의 카드, 최대 1~10 기본 전력
*R = 로봇 난이도 높은 카드
*SOLO = 로봇 솔로 챌린지 카드
세트
스타터 카드를 포함한 도시 카드 세트는 항상 게임에 있습니다. 6개의 추가 세트가 있지만 각 게임에는 5개만 사용되므로 다양한 덱 조합이 가능합니다. 로봇 상대가 사용되면 자체 세트가 있습니다.
스타터 및 로봇 카드를 제외하고 각 세트에는 카드가 "희귀" 또는 "일반"을 지정하지 않는 한 모든 카드의 4개 사본이 포함됩니다. 이 경우 카드 자체에 사본 수가 표시됩니다.
덱 단계
플레이어는 5장의 카드로 구성된 무작위 비밀 전열대에서 덱에 1~2장의 카드를 추가합니다. 플레이어는 이 전열대를 버리고 덱 페이즈당 한 번 뽑을 수 있습니다. 마지막으로 플레이어는 하나 이상의 카드를 제거하여 덱를 다듬을 수 있습니다.
이후 라운드에서 플레이어는 더 강력한 B 또는 C 카드 전열대를 선택할 수 있습니다.
매치 단계
각 플레이어는 자동으로 덱을 섞고 한 명의 상대와 짝을 이룹니다. 각 플레이어는 자신의 덱에서 카드를 공개하여 깃발을 포획하고 유지하기 위해 경쟁합니다. 여러 2인용 매치가 마치 각자의 미니게임인 것처럼 동시에 진행됩니다.
게임플레이
각 경기는 깃발을 놓고 싸우는 플레이어로 구성되며, 깃발은 점령될 때 앞뒤로 움직입니다. 경기는 깃발을 소유한 트로피 번호가 가장 높은 플레이어부터 시작됩니다. 동점이 있으면 임의의 플레이어가 깃발을 가지고 시작합니다. 이 플레이어는 자신의 덱 맨 위 카드를 공개하고 그 위에 깃발을 놓습니다. 카드에 발생해야 하는 효과가 있으면 이때 발생합니다.
다음으로 상대방은 깃발을 뺏기 위해 공격해야 합니다. 그들은 섞인 덱 맨 위에서 카드를 한 번에 하나씩 공개하여 공격합니다. 공개된 각 공격 카드의 기본 전력을 합산하여 방어 카드의 기본 전력과 비교합니다. 또한 일부 카드 효과는 공격측 또는 방어측의 힘을 수정할 수 있습니다.
공격자의 파워가 방어자의 파워와 같거나 크면 방어자는 자신의 카드를 벤치의 열린 슬롯(6개의 칸이 있는 영역)으로 옮깁니다. 각 벤치 칸에는 카드 이름이 같은 카드를 얼마든지 넣을 수 있지만 하나의 칸에 이름이 다른 두 장의 카드를 넣을 수는 없습니다.
마지막으로, 공격자는 공개된 모든 카드를 함께 밀어 맨 위에 보이는 카드가 1개만 있는 스택을 형성합니다. 깃발은 이제 깃발을 가지고 방어하는 이 카드로 이동됩니다. 방어력은 자신과 "벤치에서" 카드 효과만 고려하며 그 아래에 숨겨진 카드는 고려하지 않습니다.
이제 주기가 반복됩니다. 다른 플레이어는 합친 힘이 방어력과 같거나 커질 때까지 카드를 공개하여 공격합니다. 방어자는 카드를 벤치로 옮기고 공격자가 되는 식입니다.
경기 종료
플레이어가 자신의 덱에서 카드를 뽑아야 하는데 그럴 수 없으면 경기가 종료됩니다.
또한 플레이어가 카드를 벤치로 옮겨야 하고 칸이 충분하지 않은 경우(비어 있거나 들어오는 카드와 동일한 이름을 가진 경우) 매치가 종료됩니다.
두 경우 모두 해당 플레이어는 패배합니다. 그들의 상대는 현재 라운드의 트로피를 얻습니다. 각 트로피에는 반대쪽에 별표로 표시되는 비밀 번호의 팬이 있습니다. 1라운드 트로피는 팬이 2~3명뿐이지만 7라운드 트로피는 9~10명의 팬이 있습니다!
트로피 팬은 3-8인용 게임에서는 최종 라운드까지 비밀로 유지되며 1-2인용 게임에서는 공개됩니다.
새로운 라운드
각 라운드는 선택할 수 있는 더 강력한 카드를 제공할 수 있습니다. 각 라운드는 또한 3-8인용 게임에서 플레이어를 새로운 상대와 매치시킵니다.
카드 효과
카드에 굵게 표시된 키워드가 없으면 카드가 공개될 때 효과가 발생합니다. 효과는 최대한 해결됩니다. 카드가 즉각적인 파워 보너스를 받으면 깃발을 소유한 상태에서도 유지됩니다.
효과가 팬에게 주는 경우 플레이어는 공개 팬 토큰을 여러 개 가져갑니다.
어떤 효과로 카드가 소진 더미에 놓이는 경우 카드는 앞면 더미로 이동됩니다. 이 더미에는 제한이 없으며 그 안에 있는 카드는 효과가 없습니다. 카드를 소진 더미로 옮기면 벤치를 정리하여 잃지 않도록 할 수 있습니다.
효과에 굵게 표시된 키워드가 있으면 다른 방식으로 적용됩니다.
* 공격 중: 효과는 공개한 공격에만 적용됩니다. 카드 중 하나가 깃발을 소유하고 있으면 효과가 더 이상 활성화되지 않습니다.
* 벤치에서: 이 카드가 벤치에 있는 즉시 효과가 적용되고 벤치에 남아 있는 동안 활성화됩니다. 같은 이름을 가진 여러 카드의 파워 보너스는 합산됩니다.
* 깃발 소유 중: 깃발이 이 카드에 놓이는 즉시 효과가 적용되고 깃발이 남아 있는 한 활성화됩니다.
* 깃발 손실: 이 카드에서 플래그를 제거하면 해당 효과가 해결됩니다. 따라서 이 카드는 미리 깃발을 소지하고 있어야 합니다. 깃발 상실 효과는 카드가 깃발을 소유할 때 적용되는 효과보다 먼저 해결됩니다.
* 선택 시(우주 세트에서만): 이 카드를 선택한 덱 페이즈에서 한 번만 효과가 발동됩니다.
파이널 라운드
3-8인용 게임의 경우 각 플레이어는 자신이 수집한 트로피에서 팬을 공개합니다. 이 값은 플레이어가 보유한 모든 공개 팬 토큰에 추가됩니다. 가장 많은 팬을 보유한 2명의 선수가 결승전에 진출하며, 나머지 선수들은 모두 관중일 뿐입니다. 대부분의 팬이 동점인 경우, 가장 많은 트로피를 획득한 플레이어가 동점을 해제한 다음 라운드 번호가 가장 높은 트로피를 보유한 플레이어가 동점을 결정합니다. 결승전 전에는 새로운 카드가 없지만 각 결승 진출자는 자신의 덱에서 카드를 제거할 수 있습니다.
1~2인 게임의 경우 최종 라운드가 없으며, 7라운드 이후 또는 아래 설명과 같이 더 일찍 게임이 종료됩니다.
게임 종료
3~8인용 게임의 경우 최종 라운드가 끝나면 게임이 종료됩니다. 최종 라운드의 승자는 총 팬 수에 관계없이 전체 게임에서 승리합니다.
1~2인 플레이어의 경우 플레이어가 매치 페이즈 후 최소 11명의 팬을 확보하면 즉시 승리합니다. 그렇지 않으면 7라운드 후 총 팬이 가장 많은 플레이어가 승리합니다.
로봇 상대
플레이어 수가 홀수인 게임의 경우 로봇 상대가 포함됩니다. 로봇은 자체 스타터 카드 덱을 가지고 있으며 덱 단계에 참여하지 않습니다. 로봇은 난이도 1~5로 설정할 수 있습니다. 레벨 4와 5는 강력하며 불공평하게 느껴질 수 있으므로 멀티플레이어 게임에 적합하지 않습니다.
더 높은 로봇 난이도 레벨은 로봇의 스타터 카드를 더 강한 카드의 무작위 선택으로 대체합니다.
3-7인용 게임에서 로봇은 획득한 트로피를 보관하지 않습니다. 따라서 팬을 얻지 못하며 결선 진출자가 될 수 없습니다. 1인용 게임에서 로봇은 트로피를 보관하고 이를 통해 팬을 확보합니다.
솔로 모드
인간 플레이어는 로봇 상대와 대결할 수 있습니다. 매치 페이즈 후 최소 11명의 팬을 확보하여 조기에 승리할 수 있는 가능성을 포함하여 2인 게임에 대한 규칙을 따릅니다.
또한 솔로 모드 설정에는 "솔로 스페셜 챌린지" 옵션이 포함됩니다. 이 기능을 활성화하면 로봇의 데크에 하나 이상의 "SOLO" 카드가 포함될 가능성이 있어 훨씬 더 어려워집니다.
4e7e26ae04b350016d82d1371a8992c224dfd060
1470
1469
2023-06-06T02:41:52Z
Kimbob128
8968
wikitext
text/x-wiki
요약
플레이어는 7라운드 동안 드래프트("덱 단계") 및 카드 공개("매치 단계") 단계에 참여합니다.
이후 3~8인 게임의 경우 7라운드를 모두 마친 후 가장 많은 팬을 보유한 2명의 플레이어만이 결승전에 진출할 수 있습니다.
1~2인의 경우 결승전이 없으며 가장 많은 팬을 모은 플레이어가 승리합니다. 1~2인 플레이어의 경우 플레이어가 매치 페이즈 후 최소 11명의 팬을 모으면 즉시 승리합니다.
카드종류
각 카드의 상단 모서리에는 기본 능력이 표시되고 상단에는 카드 세트 아이콘이 표시됩니다. 카드의 오른쪽 하단에는 레벨을 설명하는 문자도 있습니다.
*S = 스타터 카드
*A = 저레벨 카드, 최대 1~3 기본 전력
*B = 중급레벨의 카드, 최대 1~5 기본 전력
*C = 높은 수준레벨의 카드, 최대 1~10 기본 전력
*R = 로봇 난이도 높은 카드
*SOLO = 로봇 솔로 챌린지 카드
세트
스타터 카드를 포함한 도시 카드 세트는 항상 게임에 있습니다. 6개의 추가 세트가 있지만 각 게임에는 5개만 사용되므로 다양한 덱 조합이 가능합니다. 로봇 상대가 사용되면 자체 세트가 있습니다.
스타터 및 로봇 카드를 제외하고 각 세트에는 카드가 "희귀" 또는 "일반"을 지정하지 않는 한 모든 카드의 4개 사본이 포함됩니다. 이 경우 카드 자체에 사본 수가 표시됩니다.
덱 단계
플레이어는 5장의 카드로 구성된 무작위 비밀 전열대에서 덱에 1~2장의 카드를 추가합니다. 플레이어는 이 전열대를 버리고 덱 페이즈당 한 번 뽑을 수 있습니다. 마지막으로 플레이어는 하나 이상의 카드를 제거하여 덱를 다듬을 수 있습니다.
이후 라운드에서 플레이어는 더 강력한 B 또는 C 카드 전열대를 선택할 수 있습니다.
매치 단계
각 플레이어는 자동으로 덱을 섞고 한 명의 상대와 짝을 이룹니다. 각 플레이어는 자신의 덱에서 카드를 공개하여 깃발을 포획하고 유지하기 위해 경쟁합니다. 여러 2인용 매치가 마치 각자의 미니게임인 것처럼 동시에 진행됩니다.
게임플레이
각 경기는 깃발을 놓고 싸우는 플레이어로 구성되며, 깃발은 점령될 때 앞뒤로 움직입니다. 경기는 깃발을 소유한 트로피 번호가 가장 높은 플레이어부터 시작됩니다. 동점이 있으면 임의의 플레이어가 깃발을 가지고 시작합니다. 이 플레이어는 자신의 덱 맨 위 카드를 공개하고 그 위에 깃발을 놓습니다. 카드에 발생해야 하는 효과가 있으면 이때 발생합니다.
다음으로 상대방은 깃발을 뺏기 위해 공격해야 합니다. 그들은 섞인 덱 맨 위에서 카드를 한 번에 하나씩 공개하여 공격합니다. 공개된 각 공격 카드의 기본 전력을 합산하여 방어 카드의 기본 전력과 비교합니다. 또한 일부 카드 효과는 공격측 또는 방어측의 힘을 수정할 수 있습니다.
공격자의 파워가 방어자의 파워와 같거나 크면 방어자는 자신의 카드를 벤치의 열린 슬롯(6개의 칸이 있는 영역)으로 옮깁니다. 각 벤치 칸에는 카드 이름이 같은 카드를 얼마든지 넣을 수 있지만 하나의 칸에 이름이 다른 두 장의 카드를 넣을 수는 없습니다.
마지막으로, 공격자는 공개된 모든 카드를 함께 밀어 맨 위에 보이는 카드가 1개만 있는 스택을 형성합니다. 깃발은 이제 깃발을 가지고 방어하는 이 카드로 이동됩니다. 방어력은 자신과 "벤치에서" 카드 효과만 고려하며 그 아래에 숨겨진 카드는 고려하지 않습니다.
이제 주기가 반복됩니다. 다른 플레이어는 합친 힘이 방어력과 같거나 커질 때까지 카드를 공개하여 공격합니다. 방어자는 카드를 벤치로 옮기고 공격자가 되는 식입니다.
경기 종료
플레이어가 자신의 덱에서 카드를 뽑아야 하는데 그럴 수 없으면 경기가 종료됩니다.
또한 플레이어가 카드를 벤치로 옮겨야 하고 칸이 충분하지 않은 경우(비어 있거나 들어오는 카드와 동일한 이름을 가진 경우) 매치가 종료됩니다.
두 경우 모두 해당 플레이어는 패배합니다. 그들의 상대는 현재 라운드의 트로피를 얻습니다. 각 트로피에는 반대쪽에 별표로 표시되는 비밀 번호의 팬이 있습니다. 1라운드 트로피는 팬이 2~3명뿐이지만 7라운드 트로피는 9~10명의 팬이 있습니다!
트로피 팬은 3-8인용 게임에서는 최종 라운드까지 비밀로 유지되며 1-2인용 게임에서는 공개됩니다.
새로운 라운드
각 라운드는 선택할 수 있는 더 강력한 카드를 제공할 수 있습니다. 각 라운드는 또한 3-8인용 게임에서 플레이어를 새로운 상대와 매치시킵니다.
카드 효과
카드에 굵게 표시된 키워드가 없으면 카드가 공개될 때 효과가 발생합니다. 효과는 최대한 해결됩니다. 카드가 즉각적인 파워 보너스를 받으면 깃발을 소유한 상태에서도 유지됩니다.
효과가 팬에게 주는 경우 플레이어는 공개 팬 토큰을 여러 개 가져갑니다.
어떤 효과로 카드가 소진 더미에 놓이는 경우 카드는 앞면 더미로 이동됩니다. 이 더미에는 제한이 없으며 그 안에 있는 카드는 효과가 없습니다. 카드를 소진 더미로 옮기면 벤치를 정리하여 잃지 않도록 할 수 있습니다.
효과에 굵게 표시된 키워드가 있으면 다른 방식으로 적용됩니다.
* 공격 중: 효과는 공개한 공격에만 적용됩니다. 카드 중 하나가 깃발을 소유하고 있으면 효과가 더 이상 활성화되지 않습니다.
* 벤치에서: 이 카드가 벤치에 있는 즉시 효과가 적용되고 벤치에 남아 있는 동안 활성화됩니다. 같은 이름을 가진 여러 카드의 파워 보너스는 합산됩니다.
* 깃발 소유 중: 깃발이 이 카드에 놓이는 즉시 효과가 적용되고 깃발이 남아 있는 한 활성화됩니다.
* 깃발 손실: 이 카드에서 플래그를 제거하면 해당 효과가 해결됩니다. 따라서 이 카드는 미리 깃발을 소지하고 있어야 합니다. 깃발 상실 효과는 카드가 깃발을 소유할 때 적용되는 효과보다 먼저 해결됩니다.
* 선택 시(우주 세트에서만): 이 카드를 선택한 덱 페이즈에서 한 번만 효과가 발동됩니다.
파이널 라운드
3-8인용 게임의 경우 각 플레이어는 자신이 수집한 트로피에서 팬을 공개합니다. 이 값은 플레이어가 보유한 모든 공개 팬 토큰에 추가됩니다. 가장 많은 팬을 보유한 2명의 선수가 결승전에 진출하며, 나머지 선수들은 모두 관중일 뿐입니다. 대부분의 팬이 동점인 경우, 가장 많은 트로피를 획득한 플레이어가 동점을 해제한 다음 라운드 번호가 가장 높은 트로피를 보유한 플레이어가 동점을 결정합니다. 결승전 전에는 새로운 카드가 없지만 각 결승 진출자는 자신의 덱에서 카드를 제거할 수 있습니다.
1~2인 게임의 경우 최종 라운드가 없으며, 7라운드 이후 또는 아래 설명과 같이 더 일찍 게임이 종료됩니다.
게임 종료
3~8인용 게임의 경우 최종 라운드가 끝나면 게임이 종료됩니다. 최종 라운드의 승자는 총 팬 수에 관계없이 전체 게임에서 승리합니다.
1~2인 플레이어의 경우 플레이어가 매치 페이즈 후 최소 11명의 팬을 확보하면 즉시 승리합니다. 그렇지 않으면 7라운드 후 총 팬이 가장 많은 플레이어가 승리합니다.
로봇 상대
플레이어 수가 홀수인 게임의 경우 로봇 상대가 포함됩니다. 로봇은 자체 스타터 카드 덱을 가지고 있으며 덱 단계에 참여하지 않습니다. 로봇은 난이도 1~5로 설정할 수 있습니다. 레벨 4와 5는 강력하며 불공평하게 느껴질 수 있으므로 멀티플레이어 게임에 적합하지 않습니다.
더 높은 로봇 난이도 레벨은 로봇의 스타터 카드를 더 강한 카드의 무작위 선택으로 대체합니다.
3-7인용 게임에서 로봇은 획득한 트로피를 보관하지 않습니다. 따라서 팬을 얻지 못하며 결선 진출자가 될 수 없습니다. 1인용 게임에서 로봇은 트로피를 보관하고 이를 통해 팬을 확보합니다.
솔로 모드
인간 플레이어는 로봇 상대와 대결할 수 있습니다. 매치 페이즈 후 최소 11명의 팬을 확보하여 조기에 승리할 수 있는 가능성을 포함하여 2인 게임에 대한 규칙을 따릅니다.
또한 솔로 모드 설정에는 "솔로 스페셜 챌린지" 옵션이 포함됩니다. 이 기능을 활성화하면 로봇의 덱에 하나 이상의 "SOLO" 카드가 포함될 가능성이 있어 훨씬 더 어려워집니다.
388618c3423eb083fd8ed871e35c5ac18b32bb6c
Gamehelprainbow
0
255
1471
2023-06-16T04:14:03Z
Hyohyohyohyohyohyo
8998
새 문서: 요약 레인보우는 9개의 다른 색상의 카드를 사용하여 두 명의 플레이어가 겨루는 카드 게임입니다. 각 카드는 앞면/뒷면에 2가지 색상이 있습니다. 플레이어는 카드 3장을 손에 들고 처음에는 카드 뒷면의 두 번째 색상을 볼 수 없는 반면, 상대방은 카드 뒷면을 볼 수 있습니다. 플레이어는 차례로 공통 영역(테이블)에서 카드를 플레이합니다. 게임의 목적은 상대...
wikitext
text/x-wiki
요약
레인보우는 9개의 다른 색상의 카드를 사용하여 두 명의 플레이어가 겨루는 카드 게임입니다. 각 카드는 앞면/뒷면에 2가지 색상이 있습니다.
플레이어는 카드 3장을 손에 들고 처음에는 카드 뒷면의 두 번째 색상을 볼 수 없는 반면, 상대방은 카드 뒷면을 볼 수 있습니다.
플레이어는 차례로 공통 영역(테이블)에서 카드를 플레이합니다.
게임의 목적은 상대보다 더 많은 카드를 이기는 것입니다.
전술, 조합 기술, 그리고 좋은 기억력이 승리에 필요합니다.
게임준비
1. 모든 카드를 잘 섞어서 카드 홀더에 넣습니다
2. 각자 카드 더미의 한 면만 보이도록 두 플레이어 사이에 카드 홀더를 놓습니다
3. 각자 더미에서 카드 3장을 가져와 손에 듭니다. 카드 뒷면은 상대방만 확인할 수 있습니다.
게임진행
1. 카드 뒤집기
두 장 이상의 카드를 내려놓으려면 카드를 내려놓기 전 플레이 영역에 이미 놓여있는 카드 중 하나를 뒤집어야 합니다. * 첫 번째 카드를 내려놓을 때는 필수 행동이 아닙니다.
2. 카드 내려놓기
손에 든 카드를 앞면 또는 뒷면으로 내려놓을 수 있습니다.
플레이 영역 확인
카드를 뒤집거나 내려놓은 후에는 플레이 영역에 놓인 카드를 확인합니다.
- 통과
플레이 영역에 놓인 카드가 5장 이하이고, 모두 다른 색깔이라면 통과입니다.
흰색 카드는 만능 카드로 원하는 색깔로 사용할 수 있습니다.
- 오류
이미 플레이 영역에 있는 색깔과 중복인 카드 혹은 검정색 카드를 내려놓거나 뒤집으면, 즉시 그 라운드에서 패배합니다. 플레이 영역에 놓인 모든 카드를 상대방이 가져가고, 패배한 플레이어부터 다음 라운드를 시작합니다.
- 레인보우
플레이 영역에 여섯 번째 카드를 내려놓고, 모든 카드의 색깔이 다르다면 레인보우을 완성합니다. 완성힌 플레이어가 플레이 영역에 놓인 6장의 카드를 모두 가져갑니다.
차례종료
자신의 차레를 마칠 때, 손에 카드 3장이 되도록 카드를 가져옵니다.
게임종료
더미가 다 쩔어서져 손에 3장의 카드를 채울 수 없다면 게임을 즉시 종료합니다. 더 많은 카드를 모은 플레이어가 승리합니다.
3b6707fa9d9eaf937ff37794b2dfe338f82ff0d3
Gamehelpgizmos
0
245
1473
1442
2023-06-27T19:22:21Z
Stoolmaker
9024
wikitext
text/x-wiki
== 개요 ==
기즈모는 엔진 빌딩 자원 관리 게임입니다. 여러분은 하나의 액션으로 구성된 간단한 턴부터 시작하여 엔진을 빌드업하여 한 턴에 많은 액션을 발동할 수 있는 지점까지 진행할 것입니다
플레이어의 차례입니다
다음 작업 중 하나를 수행해야 합니다:
수집: 디스플레이 영역에서 기즈모를 하나 수집합니다.
획득: 에너지 레일에서 선택한 에너지 1개를 획득합니다.
제작: 디스플레이 영역 또는 아카이브에서 1개의 기즈모를 빌드합니다.
연구: 3개의 레벨 덱 중 하나에서 기즈모 카드를 뽑고 수집 또는 제작할 1개를 선택합니다
==수집==
디스플레이 영역에서 1개의 기즈모 카드를 선택한 다음 수집을 선택합니다. 기즈모 수집 후 즉시 해당 덱의 상단 카드로 교체됩니다. 이 새 기즈모를 뽑으면 수집 작업이 종료됩니다.
플레이어 대시보드의 업그레이드 영역에 표시된 만큼 수집에는 수집할 수 있는 기즈모 수가 제한됩니다. 각 플레이어는 수집 제한을 1로 설정하고 게임을 시작하지만, 일부 업그레이드 기즈모는 이 수를 늘립니다. 보관 파일은 파일 제한보다 많은 크기를 보관할 수 없으므로, 제한에 도달하면 파일 작업을 수행할 수 없습니다.
==획득==
에너지 레일에 있는 6개 중 1개의 에너지를 선택하여 에너지 저장 링에 추가합니다. 플레이어 대시보드의 업그레이드 영역에 표시된 만큼 에너지 저장 링에 저장할 수 있는 에너지가 제한되어 있습니다. 각 플레이어는 저장 제한을 5로 설정하고 게임을 시작하지만 일부 압그레이드 기즈모는 이 수를 늘릴 것입니다. 링에는 에너지 저장 한도 이상의 에너지를 저장할 수 없으므로, 한계에 도달하면 기존의 에너지를 사용하지 않는 한 더 이상의 에너지를 수집할 수 없습니다.
중요: 일부 기능을 사용하면 임의 에너지를 뽑을 수 있습니다. 이 작업은 획득 작업이 아니므로 다른 작업을 트리거하지 않습니다.
==제작==
디스플레이 영역 또는 아카이브에서 1개의 기즈모 카드를 선택합니다. 기즈모의 에너지 유형과 비용에 맞는 에너지 저장 링의 에너지를 사용하십시오. 디스플레이 영역에서 기즈모를 만든 후 즉시 해당 덱 상단에서 새로운 기즈모로 교체됩니다. 보충 후 제작 작업이 종료됩니다.
제작한 기즈모는 플레이어 대시보드 아래로 이동하여 모든 효과를 볼 수 있습니다.
==변환==
제작 작업을 수행할 때 변환 기즈모를 사용하여 보유한 에너지를 필요한 에너지로 변환할 수 있습니다. 보유한 변환기를 선택하여 이 작업을 수행할 수 있습니다. 변환기 유형에 대한 자세한 내용은 링크된 효과 목록 PDF에서 확인할 수 있습니다.
==연구==.
레벨 덱(1, 2 또는 3)을 선택하고 연구량과 동일한 카드 수를 그립니다. 한 번에 두 개 이상의 레벨 덱에서 뽑을 수 없습니다. 각 플레이어는 연구량 3으로 게임을 시작하지만, 일부 업그레이드 기즈모는 그 수를 늘립니다. 선택한 레벨 덱의 카드 수가 연구량 보다 적을 경우 사용 가능한 카드 수만 뽑습니다. 카드를 뽑은 후 1개를 선택하고 제작(에너지가 충분한 경우) 또는 수집(Archive에 공간이 있는 경우)을 선택합니다. 또는 둘 다 수행하지 않고 통과하도록 선택할 수 있습니다.
그런 다음 나머지 카드는 선택한 순서대로 해당 레벨 덱의 맨 아래로 돌아갑니다.
참고: 연구 작업 중에 수행하는 파일 또는 빌드 작업도 기즈모를 트리거하는 데 카운트됩니다(아래 Gizmo 효과 트리거 참조).
==기즈모 효과 트리거==
사용 가능한 4가지 액션 중 하나를 취하는 것이 게임의 기본이지만, 게임의 진정한 핵심(그리고 승리의 열쇠)은 당신의 차례에 훨씬 더 많은 것을 얻기 위해 당신의 기즈모의 효과를 발동시키는 것입니다. 플레이어 대시보드 아래에 제작하고 배치하는 모든 기즈모에는 특정 트리거에 의해 활성화되는 효과가 있습니다(이에 대한 자세한 내용은 효과 목록의 링크된 PDF 참조). 작업을 수행할 때마다 트리거된 기즈모가 강조 표시됩니다. 트리거 작업이 완료된 후 원하는 순서로 트리거된 기즈모의 효과를 활성화할 수 있습니다. 트리거 조건이 두 번 이상 충족되더라도 각 기즈모는 한 번에 한 번만 사용할 수 있습니다.
참고: 기즈모가 만들어진 턴에도 기즈모의 효과를 사용할 수 있습니다. 그러나 제작한 작업과 동일한 작업에 의해 트리거될 수 없습니다.
==연쇄 반응==
최고의 발명가들의 비밀은 하나의 기즈모가 다른 기즈모를 촉발시켜 많은 이익을 창출하는 연쇄 반응을 일으킬 방법으로 기즈모를 민드는 것입니다! 기즈모 하나의 효과는 원래 수행된 액션과 다른 액션일 수 있습니다. 그런 다음 보조 작업을 수행하면 다른 기즈모를 트리거할 수 있습니다. 작업을 수행할 때마다 해당 순서에 대한 하나의 작업이든, 기즈모 효과에 의해 트리거된 작업이든 상관없이 항상 해당 작업의 기즈모를 확인하여 트리거된 작업이 있는지 확인하십시오.
활성화할 수 있는 기즈모의 수에는 제한이 없지만, 각 기즈모는 한 번에 한 번만 사용할 수 있다는 것을 항상 기억하십시오.
각 Gizmo의 효과가 실행되는 순서는 효과가 발생한 순서에 관계없이 플레이어에게 달려 있습니다. 연쇄 반응의 처음에 만들어진 기즈모는 그것을 만든 행동에 의해 촉발되지 않는 한, 그 연쇄 반응의 나중에 활성화될 수 있습니다. 때로는 작업과 효과를 실행하기 위한 최적의 순서를 찾는 것이 더 큰 결과를 얻을 수 있습니다.
==게임의 끝==
게임의 끝은 플레이어가 4번째 레벨 3 기즈모 또는 16번째 기즈모(시작 기즈모 포함)를 제작할 때 입니다. 그러면 첫 번째 플레이어의 오른쪽에 있는 플레이어가 차례를 마칠 때까지 게임이 계속됩니다. 즉, 모든 플레이어가 게임에서 동일한 턴 수를 가질 때까지입니다. 게임 종료를 트리거한 플레이어가 첫 번째 플레이어의 오른쪽에 있는 플레이어일 경우, 차례가 끝나면 게임이 종료됩니다.
당연히 승리 포인트가 가장 많은 선수가 승리합니다! 동점일 경우, 액티브 기즈모 영역에서 가장 많은 기즈모를 가진 동점자가 승리합니다(필드 기즈모는 포함되지 않음). 여전히 동점일 경우, 에너지 저장 링에 가장 많은 에너지가 남아 있는 동점자가 승리합니다. 그래도 동점일 경우 레벨 3 기즈모가 많은 사람이 승리하고, 그래도 동점일 경우 첫 번째 플레이어에서 가장 멀리 있는 동점자가 승리합니다.
3ec6238e2a50968e2d1974efa515b44d148b8da0
Gamehelpevergreen
0
256
1474
2023-08-03T09:28:18Z
APPAi
8420
새 문서: 개요 게임은 14라운드(봄 5라운드, 여름 4라운드, 가을 3라운드, 겨울 2라운드)에 걸쳐 진행됩니다. 드래프트 플레이어 수 + 1과 같은 수의 카드에서 생물군계 카드를 뽑습니다. 첫 번째 플레이어는 자신의 카드를 고른 후 가장 왼쪽 카드에 첫 번째 플레이어 마커를 놓아 이 카드를 고른 사람이 새로운 첫 번째 플레이어가 됩니다. 선택하지 않은 카드는 상단에 아이콘...
wikitext
text/x-wiki
개요
게임은 14라운드(봄 5라운드, 여름 4라운드, 가을 3라운드, 겨울 2라운드)에 걸쳐 진행됩니다.
드래프트
플레이어 수 + 1과 같은 수의 카드에서 생물군계 카드를 뽑습니다.
첫 번째 플레이어는 자신의 카드를 고른 후 가장 왼쪽 카드에 첫 번째 플레이어 마커를 놓아 이 카드를 고른 사람이 새로운 첫 번째 플레이어가 됩니다.
선택하지 않은 카드는 상단에 아이콘이 있을 수 있습니다:
비옥 (꽃) 아이콘이 있을 수 있습니다: 카드를 해당 생물군과 일치하는 비옥도 구역에 놓으면, 아이콘의 합이 해당 생물군의 비옥도 값을 나타냅니다.
건조 (해골) : 해당 생물군과 일치하는 비옥도 영역에 있는 가장 최근의 카드를 뒤집어 그 카드가 제공한 아이콘을 제거한 다음,
해당 생물군의 비옥도 영역에 건조도 카드를 추가합니다.
아이콘 없음 : 카드를 버립니다.
행동
매 턴마다 한 가지 행동을 취합니다.
행동은 다음 중 하나로 줄일 수 있습니다: 새싹 나무를 놓거나, 새싹 나무를 작은 나무로 바꾸거나, 작은 나무를 큰 나무로 바꿉니다.
구체적으로, 이 행동에는 4가지 버전이 있으며, 그 중 3가지 버전은 카드의 생물군에 속하는 공간에서 일어납니다:
1) 새싹 트리플을 최대 3개까지 심습니다.
2) 새싹 트리플을 작은 나무로 변경하거나 작은 나무를 큰 나무로 변경하여 두 개의 별도 공간에 놓습니다.
3) 한 공간에 새싹 트리플을 심은 후, 다른 공간에서 새싹 트리플을 작은 나무로 변경하거나 작은 나무를 큰 나무로 변경합니다.
4) 새싹 나무를 심거나, 새싹 나무를 작은 나무로 바꾸거나, 작은 나무를 큰 나무로 바꾸거나, 카드의 생물군에 제한되지 않은 공간에
새싹 나무를 심거나 작은 나무를 큰 나무로 바꿉니다.
능력
각 카드에는 자신의 턴에 사용할 수 있는 능력이 있습니다.
능력은 행동 전후에 사용할 수 있지만, 행동 사이에는 사용할 수 없습니다(즉, 방해할 수 없습니다).
능력은 카드의 생물군에 의해 제한되지 않습니다.
능력을 사용하면, 그 능력의 레벨이 1 증가합니다.
새로운 능력 레벨은 해당 능력으로 행동할 수 있는 횟수입니다(예: 능력 레벨이 2이면 해당 능력을 두 번 실행할 수 있습니다).
6가지 능력은 다음과 같습니다:
1) 새싹 트리플 1개 배치
2) 새싹 트리플을 작은 나무로 변경하기
3) 작은 나무를 큰 나무로 변경하기
4) 덤불 1개 배치
5) 호수 1개를 배치한 다음 방금 배치한 호수와 인접한 두 칸에 새싹 나무를 작은 나무로 또는 작은 나무를 큰 나무로 변경합니다.
6) 새싹에서 자신의 파워 레벨과 같은 점수를 얻습니다.
라운드 종료
일반 라운드 종료는 초안으로 돌아가 위 과정을 반복합니다.
5, 9, 12, 14 라운드에도 시즌 종료가 있습니다.
시즌 종료
보드에서 태양의 위치에 따라 모든 기둥/열의 빛의 방향이 결정됩니다.
크기가 같거나 큰 나무는 그림자 선에 있는 뒤에 있는 나무의 빛을 차단합니다.
작은 나무는 그림자 선이 1입니다.
큰 나무는 그림자 선이 2입니다.
예: 작은나무 작은나무 큰나무 빈칸 큰나무의 선에서 첫 번째 작은 나무는 빛을 받고,
두 번째 작은 나무는 빛을 받지 못하며, 두 개의 큰 나무도 빛을 받습니다.
빛을 모으는 작은 나무 점수 1점
빛을 모으는 큰 나무는 2점
다른 구성물은 빛을 얻거나 차단하지 않습니다.
또한, 인접한 작은 나무, 큰 나무, 덤불을 가장 많이 모아서 앞서 언급한 특징당 1점을 얻습니다.
이제 수집한 생물군계 카드를 모두 버리고 태양을 시계 방향으로 다음 위치로 이동합니다.
게임 종료
위와 같이 시즌 점수를 획득한 후 겨울이 끝나면 게임이 종료됩니다.
시즌 점수 외에도 다음을 수행합니다:
비옥도 영역에는 각 생물 군계의 꽃 아이콘 수가 표시되며, 해당 생물 군계의 큰 나무마다 해당 점수를 획득할 수 있습니다.
예: 바위에 꽃 아이콘이 5개 있고, 바위에 큰 나무가 3개 있으므로 15점을 얻습니다.
가장 많은 점수를 얻은 플레이어가 승리합니다.
f3bed56817cefb4b09dd056d3cc83244cfda74dd
1475
1474
2023-08-03T09:29:43Z
APPAi
8420
wikitext
text/x-wiki
=== 개요 ===
게임은 14라운드(봄 5라운드, 여름 4라운드, 가을 3라운드, 겨울 2라운드)에 걸쳐 진행됩니다.
드래프트
플레이어 수 + 1과 같은 수의 카드에서 생물군계 카드를 뽑습니다.
첫 번째 플레이어는 자신의 카드를 고른 후 가장 왼쪽 카드에 첫 번째 플레이어 마커를 놓아 이 카드를 고른 사람이 새로운 첫 번째 플레이어가 됩니다.
선택하지 않은 카드는 상단에 아이콘이 있을 수 있습니다:
비옥 (꽃) 아이콘이 있을 수 있습니다: 카드를 해당 생물군과 일치하는 비옥도 구역에 놓으면, 아이콘의 합이 해당 생물군의 비옥도 값을 나타냅니다.
건조 (해골) : 해당 생물군과 일치하는 비옥도 영역에 있는 가장 최근의 카드를 뒤집어 그 카드가 제공한 아이콘을 제거한 다음,
해당 생물군의 비옥도 영역에 건조도 카드를 추가합니다.
아이콘 없음 : 카드를 버립니다.
=== '''행동''' ===
매 턴마다 한 가지 행동을 취합니다.
행동은 다음 중 하나로 줄일 수 있습니다: 새싹 나무를 놓거나, 새싹 나무를 작은 나무로 바꾸거나, 작은 나무를 큰 나무로 바꿉니다.
구체적으로, 이 행동에는 4가지 버전이 있으며, 그 중 3가지 버전은 카드의 생물군에 속하는 공간에서 일어납니다:
1) 새싹 트리플을 최대 3개까지 심습니다.
2) 새싹 트리플을 작은 나무로 변경하거나 작은 나무를 큰 나무로 변경하여 두 개의 별도 공간에 놓습니다.
3) 한 공간에 새싹 트리플을 심은 후, 다른 공간에서 새싹 트리플을 작은 나무로 변경하거나 작은 나무를 큰 나무로 변경합니다.
4) 새싹 나무를 심거나, 새싹 나무를 작은 나무로 바꾸거나, 작은 나무를 큰 나무로 바꾸거나, 카드의 생물군에 제한되지 않은 공간에 새싹 나무를 심거나 작은 나무를 큰 나무로 바꿉니다.
=== 능력 ===
각 카드에는 자신의 턴에 사용할 수 있는 능력이 있습니다.
능력은 행동 전후에 사용할 수 있지만, 행동 사이에는 사용할 수 없습니다(즉, 방해할 수 없습니다).
능력은 카드의 생물군에 의해 제한되지 않습니다.
능력을 사용하면, 그 능력의 레벨이 1 증가합니다.
새로운 능력 레벨은 해당 능력으로 행동할 수 있는 횟수입니다(예: 능력 레벨이 2이면 해당 능력을 두 번 실행할 수 있습니다).
6가지 능력은 다음과 같습니다:
1) 새싹 트리플 1개 배치
2) 새싹 트리플을 작은 나무로 변경하기
3) 작은 나무를 큰 나무로 변경하기
4) 덤불 1개 배치
5) 호수 1개를 배치한 다음 방금 배치한 호수와 인접한 두 칸에 새싹 나무를 작은 나무로 또는 작은 나무를 큰 나무로 변경합니다.
6) 새싹에서 자신의 파워 레벨과 같은 점수를 얻습니다.
=== 라운드 종료 ===
일반 라운드 종료는 초안으로 돌아가 위 과정을 반복합니다.
5, 9, 12, 14 라운드에도 시즌 종료가 있습니다.
=== 시즌 종료 ===
보드에서 태양의 위치에 따라 모든 기둥/열의 빛의 방향이 결정됩니다.
크기가 같거나 큰 나무는 그림자 선에 있는 뒤에 있는 나무의 빛을 차단합니다.
작은 나무는 그림자 선이 1입니다.
큰 나무는 그림자 선이 2입니다.
예: 작은나무 작은나무 큰나무 빈칸 큰나무의 선에서 첫 번째 작은 나무는 빛을 받고,
두 번째 작은 나무는 빛을 받지 못하며, 두 개의 큰 나무도 빛을 받습니다.
빛을 모으는 작은 나무 점수 1점
빛을 모으는 큰 나무는 2점
다른 구성물은 빛을 얻거나 차단하지 않습니다.
또한, 인접한 작은 나무, 큰 나무, 덤불을 가장 많이 모아서 앞서 언급한 특징당 1점을 얻습니다.
이제 수집한 생물군계 카드를 모두 버리고 태양을 시계 방향으로 다음 위치로 이동합니다.
게임 종료
위와 같이 시즌 점수를 획득한 후 겨울이 끝나면 게임이 종료됩니다.
시즌 점수 외에도 다음을 수행합니다:
비옥도 영역에는 각 생물 군계의 꽃 아이콘 수가 표시되며, 해당 생물 군계의 큰 나무마다 해당 점수를 획득할 수 있습니다.
예: 바위에 꽃 아이콘이 5개 있고, 바위에 큰 나무가 3개 있으므로 15점을 얻습니다.
가장 많은 점수를 얻은 플레이어가 승리합니다.
faf7d05532fe44eff7ba66f54ac6118f8019c400
Gamehelptanghulu
0
257
1476
2023-08-04T13:05:46Z
Bsesame
9086
탕후루를 완성시켜 가장 많은 별을 획득하자!
wikitext
text/x-wiki
==내 턴에 해야하는 행동==
'''1. 주사위를 굴린다.'''
'''2. 상점에서 쇼핑을 하거나 일하러 간다 (택1)'''
===행동 설명===
;1. 주사위 굴리기
:설탕 1개 획득, 코인 1개 획득, 랜덤한 과일 획득 이렇게 3가지의 주사위 눈이 존재한다.
:설탕을 획득하게 되면 플레이어 전원에게 탕후루 꼬치를 설탕코팅할 기회를 제공합니다.
:각 플레이어들은 설탕 4개를 보유하고 있다면 완성된 스틱을 코팅 할 수 있습니다.
:스틱이 코팅되면 해당 스틱의 과일 타일들이 뒤집혀지며 각 과일 타일의 별이 1씩 추가됩니다!
:랜덤한 과일을 획득하게 되면 스틱에 추가하거나 주머니에 돌려 놓을 수 있습니다.
;2-1. 상점 쇼핑하기
:과일은 충분한 코인이 있다면 원하는 만큼 구입할 수 있습니다.
:구입한 과일은 즉시 스틱의 가장 낮은 위치에 배치해야 합니다.
:처음 구매한 과일의 가격은 1코인, 두번째 구매한 과일의 가격은 2코인, N번째 구매한 과일의 가격은 N코인 입니다. (구매 할 때 마다 다음 과일의 가격이 +1 됩니다.)
:과일을 1개만 구매할 경우 설탕 1개를 추가로 얻을 수 있습니다.
:각 과일 타일에는 각기 다른 갯수의 별이 있습니다.
:'''''화과'''''(사과 또는 체리와 비슷한 모양의 과일)는 특수 타일로 원하는 종류의 과일로 취급할 수 있습니다.
;2-2. 일 하러 가기
:일하기를 선택하면 자신의 보드판에 보이는 토큰 수 만큼 코인을 획득합니다.
:보드판 아래에 코인마커의 위치로 잔고를 확인할 수 있고, 최대 9개까지 획득 가능합니다.
==스틱 완성에 대한 보상==
스틱에 4개의 과일을 모두 놓아 완성한 경우, 보상을 받을 수 있습니다.
한 스틱에 있는 과일 종류의 수에 따라 보상이 달라집니다.
# 모두 다른 과일일 경우: 5코인
# 모두 동일한 과일일 경우: 디저트 카드 2개 (디저트 카드를 통해 별을 획득할 수 있습니다.)
# 과일이 2종류인 경우: 디저트 카드 1개 + 설탕 2개
==게임 종료 조건==
한 플레이어가 3개의 스틱을 모두 완성한 후(코팅될 필요는 없음), 모든 플레이어가 짝수 번의 턴을 가진 후에 게임이 종료됩니다.
==점수 계산==
* 스틱에 있는 과일 별 합산
* 디저트 카드에 있는 별 합산
* 설탕이 가장 많이 남은 플레이어에게 별 2개 (동점이 있는 경우, 누구도 받지 않습니다.)
별의 합산이 제일 높은 플레이어가 승리합니다.
동점이 존재할 경우 남은 코인이 더 많은 사람이 승리합니다.
3ef3d56384c6761bc2e3aa3a391e56281438a9be
1477
1476
2023-08-04T13:19:19Z
Bsesame
9086
wikitext
text/x-wiki
==내 턴에 해야하는 행동==
'''1. 주사위를 굴린다.'''
'''2. 상점에서 쇼핑을 하거나 일하러 간다 (택1)'''
===행동 설명===
;1. 주사위 굴리기
:설탕 1개 획득, 코인 1개 획득, 랜덤한 과일 획득 이렇게 3가지의 주사위 눈이 존재합니다.
:설탕을 획득하게 되면 플레이어 전원은 설탕 4개를 사용해 완성된 스틱을 코팅 할 수 있습니다. 스틱이 코팅되면 해당 스틱의 과일 타일들이 뒤집혀지며 각 과일 타일의 별이 1씩 추가됩니다!
:랜덤한 과일을 획득하게 되면 스틱에 추가하거나 주머니에 돌려 놓을 수 있습니다.
;2-1. 상점 쇼핑하기
:과일은 충분한 코인이 있다면 원하는 만큼 구입할 수 있습니다.
:구입한 과일은 즉시 스틱의 가장 낮은 위치에 배치해야 합니다.
:처음 구매한 과일의 가격은 1코인, 두번째 구매한 과일의 가격은 2코인, N번째 구매한 과일의 가격은 N코인 입니다. (구매 할 때 마다 다음 과일의 가격이 +1 됩니다.)
:과일을 1개만 구매할 경우 설탕 1개를 추가로 얻을 수 있습니다.
:각 과일 타일에는 각기 다른 갯수의 별이 있습니다.
:'''''화과'''''(사과 또는 체리와 비슷한 모양의 과일)는 특수 타일로 원하는 종류의 과일로 취급할 수 있습니다.
;2-2. 일 하러 가기
:일하기를 선택하면 자신의 보드판에 보이는 토큰 수 만큼 코인을 획득합니다.
:보드판 아래에 코인마커의 위치로 잔고를 확인할 수 있고, 최대 9개까지 획득 가능합니다.
==스틱 완성에 대한 보상==
스틱에 4개의 과일을 모두 놓아 완성한 경우, 보상을 받을 수 있습니다.
한 스틱에 있는 과일 종류의 수에 따라 보상이 달라집니다.
# 모두 다른 과일일 경우: 5코인
# 모두 동일한 과일일 경우: 디저트 카드 2개 (디저트 카드를 통해 별을 획득할 수 있습니다.)
# 과일이 2종류인 경우: 디저트 카드 1개 + 설탕 2개
==게임 종료 조건==
한 플레이어가 3개의 스틱을 모두 완성한 후(코팅될 필요는 없음), 모든 플레이어가 짝수 번의 턴을 가진 후에 게임이 종료됩니다.
==점수 계산==
* 스틱에 있는 과일 별 합산
* 디저트 카드에 있는 별 합산
* 설탕이 가장 많이 남은 플레이어에게 별 2개 (동점이 있는 경우, 누구도 받지 않습니다.)
별의 합산이 제일 높은 플레이어가 승리합니다.
동점이 존재할 경우 남은 코인이 더 많은 사람이 승리합니다.
cce65f47a9f360043a56f2b5d7223bafb275f2dd
1478
1477
2023-08-04T13:27:49Z
Bsesame
9086
wikitext
text/x-wiki
==내 턴에 해야하는 행동==
'''1. 주사위를 굴린다.'''
'''2. 상점에서 쇼핑을 하거나 일하러 간다 (택1)'''
===행동 설명===
;1. 주사위 굴리기
:설탕 1개 획득, 코인 1개 획득, 랜덤한 과일 획득 이렇게 3가지의 주사위 눈이 존재합니다.
:설탕을 획득하게 되면 플레이어 전원은 설탕 4개를 사용해 완성된 스틱을 코팅 할 수 있습니다. 스틱이 코팅되면 해당 스틱의 과일 타일들이 뒤집혀지며 각 과일 타일의 별이 1씩 추가됩니다!
:랜덤한 과일을 획득하게 되면 스틱에 추가하거나 주머니에 돌려 놓을 수 있습니다.
;2-1. 상점 쇼핑하기
:과일은 충분한 코인이 있다면 원하는 만큼 구입할 수 있습니다.
:구입한 과일은 즉시 스틱의 가장 낮은 위치에 배치해야 합니다.
:처음 구매한 과일의 가격은 1코인, 두번째 구매한 과일의 가격은 2코인, N번째 구매한 과일의 가격은 N코인 입니다. (구매 할 때 마다 다음 과일의 가격이 +1 됩니다.)
:과일을 1개만 구매할 경우 설탕 1개를 추가로 얻을 수 있습니다.
:각 과일 타일에는 각기 다른 갯수의 별이 있습니다.
:'''''화과'''''(사과 또는 체리와 비슷한 모양의 과일)는 특수 타일로 원하는 종류의 과일로 취급할 수 있습니다.
;2-2. 일 하러 가기
:일하기를 선택하면 자신의 보드판에 보이는 토큰 수 만큼 코인을 획득합니다.
:보드판 아래에 코인마커의 위치로 잔고를 확인할 수 있고, 최대 9개까지 획득 가능합니다.
==스틱 완성에 대한 보상==
스틱에 4개의 과일을 모두 놓아 완성한 경우, 보상을 받을 수 있습니다.
한 스틱에 있는 과일 종류의 수에 따라 보상이 달라집니다.
# 모두 다른 과일일 경우(ABCD): 5코인
# 모두 동일한 과일일 경우(AAAA): 디저트 카드 2개 (디저트 카드를 통해 별을 획득할 수 있습니다.)
# 과일이 2종류인 경우(AABB): 디저트 카드 1개 + 설탕 2개
==게임 종료 조건==
한 플레이어가 3개의 스틱을 모두 완성한 후(코팅될 필요는 없음), 모든 플레이어가 짝수 번의 턴을 가진 후에 게임이 종료됩니다.
==점수 계산==
* 스틱에 있는 과일 별 합산
* 디저트 카드에 있는 별 합산
* 설탕이 가장 많이 남은 플레이어에게 별 2개 (동점이 있는 경우, 누구도 받지 않습니다.)
별의 합산이 제일 높은 플레이어가 승리합니다.
동점이 존재할 경우 남은 코인이 더 많은 사람이 승리합니다.
ab87a54d3fa696c00bb325fe8d82b3751fdcf272
Tips painttheroses
0
258
1479
2023-08-09T00:39:11Z
Melody btob
9107
새 문서: - 힌트 토큰 2개 이상을 놓을 수 있도록 하는 것이 좋다.
wikitext
text/x-wiki
- 힌트 토큰 2개 이상을 놓을 수 있도록 하는 것이 좋다.
89758e6ccdfbbb74246c33c10327c3c4e37b200b
Tips sevenwonders
0
259
1480
2023-08-28T15:54:28Z
Casey y
9150
새 문서: 초보자라면 자원 카드(갈색/은색) 획득하는 데 집중하세요. 이 전략은 상대의 전략을 파악, 분석할 필요가 없습니다. 자원 카드를 3~4개 모으고, 노란색의 상업 카드도 자원 획득에 도움을 줍니다(자원을 할인된 가격에 살 수 있음). 원더(불가사의)에 은색 자원이 많이 필요한 경우가 아니면 은색 카드는 하나면 충분합니다. 노란색 상업 카드를 중심으로 경제 전략...
wikitext
text/x-wiki
초보자라면 자원 카드(갈색/은색) 획득하는 데 집중하세요. 이 전략은 상대의 전략을 파악, 분석할 필요가 없습니다. 자원 카드를 3~4개 모으고, 노란색의 상업 카드도 자원 획득에 도움을 줍니다(자원을 할인된 가격에 살 수 있음). 원더(불가사의)에 은색 자원이 많이 필요한 경우가 아니면 은색 카드는 하나면 충분합니다.
노란색 상업 카드를 중심으로 경제 전략을 취한다면 양 옆 플레이어를 신경써야 합니다. 몇몇 원더(알렉산드리아, 올림피아 B)는 자원이 많이 들지 않으므로 교역이 필요가 없습니다. 하지만 기자, 로즈처럼 자원이 특히 많이 드는 원더가 선택되었다면 이 상업 카드가 꽤 유용합니다. 또한 상업 카드 자체에는 점수가 없기 때문에 점수를 얻기 위해서는 파란색 점수 카드나 보라색 길드 카드가 많이 필요합니다. 네 개 이상의 상업 카드가 이미 있는 경우 등대는 제외될 수 있지만, 4인 경기에는 등대가 하나만 들어가기에 등대를 얻지 못할 수도 있습니다.
녹색 과학 카드를 많이 만드는 사람들을 조심하세요. 녹색 카드는 위험도도, 보상도 높습니다. 녹색 카드는 세 가지 다른 기호의 세트를 완성해야 합니다. 다른 플레이어의 보드를 보고 누군가 세트를 만들기 전에 그 카드를 처리하는 것도 좋습니다. 직접 카드를 가져가거나, 원더를 만드는 데 쓰거나, 버려서 세 개의 코인으로 교환하세요. 누군가가 세트를 만들지 못하게 하는 게 핵심입니다.
빨간색 군사 카드는 너무 많이 만들지 마시요. 상업 카드와 마찬가지로 군사 카드도 그 자체로는 점수가 없습니다. 양 옆 플레이어를 1점 차이로만 이기면 되기에, 이미 앞서고 있다면 차례를 아껴 다른 데에 투자하세요.
원더 보드 A면은 필요 자원이 적고, 수행하기 더 간단합니다. 반면 B는 여러모로 완성하기 더 어렵습니다. 그러므로 초보자에게는 A를 추천합니다. 원더의 모든 단계를 만들고자 한다면 가장 어려운 마지막 단계의 자원부터 최대한 빨리 획득하는 게 좋습니다. 물론 원더를 다 만들지 않아도 우승할 수 있습니다.
코인이 부족하지 않도록하세요. 코인이 부족하면 원하는 카드를 만들 수 없기에 손해를 봅니다. 또한 자원을 살 수도 없어지기에 가지고 있는 상업 카드(시장)도 쓸모없게 됩니다.
7 원더스는 카드 게임이기 때문에, 승점을 많이 모음과 동시에 다른 플레이어의 기회를 빼앗는 많은 전략을 취할 수 있습니다.
9d50e99e166b8c111c52ce35c7e5f6b829ab8fc5
Gamehelpcantstop
0
35
1481
1226
2023-08-29T14:29:50Z
Pio2209
9151
어색한 단어나 구절을 수정하였음
wikitext
text/x-wiki
=캔트 스탑!=
캔트 스탑(Can't Stop, 영어 직역)은 주사위를 통해 안전과 위험 사이에서 운을 시험하는 게임입니다.
==규칙==
캔트 스탑은 2부터 12까지의 11개의 열이 있는 보드와 4개의 주사위, 그리고 말(각 플레이어를 상징하는 색깔 말과, 모두가 공유하는 3개의 검정색 말)로 턴이 진행됩니다.
===턴 진행===
자신의 턴이 되면, 주사위 4개를 굴립니다. 그 뒤 주사위 4개를 적당히 2개씩 나눠서 그 두 눈금의 합에 해당하는 열을 전진시킵니다.
예시 :
* 눈금 3, 3, 4, 4가 나온 경우, (3,3), (4,4)로 나눠서 6과 8을 전진시키거나, (3,4), (3,4)로 나눠서 7을 2칸 전진시킬 수 있습니다.
* 눈금 2, 3, 4, 5가 나온 경우, (2,5), (3,4)로 나눠서 7을 2칸 전진시키거나, (2,4), (3,5)로 6과 8을, 또는 (2,3), (4,5)로 5와 9를 전진시킬 수 있습니다.
* 눈금 4, 4, 4, 6이 나온 경우, 어떻게 조합하든 (4,4), (4,6), 즉 8과 10을 전진시킬 수밖에 없습니다.
===말의 전진===
한 턴에는 최대 3개의 열까지만 전진시킬 수 있습니다. 이 열은 모두가 공유하는 3개의 검정색 말로 표시합니다. 다만, 전진을 거부할 수는 없습니다. 이미 자신의 말이 있었다면, 그 다음 칸부터 검정색 말의 전진이 시작됩니다.
예시 :
* 검정색 말을 하나도 올리지 않은 채로 (2,3), (4,5)를 이동시키고자 합니다. 이 경우, 5번 열과 9번 열에 검정색 말을 올리게 되며, 어느 하나에만 올릴 수는 없습니다.
* 검정색 말을 4번 열과 5번 열에 올린 채로 (2,3), (4,5)를 이동시키고자 합니다. 이 경우, 9번 열에 추가로 검정색 말을 올리게 되며, 5번 말에 있던 검정색 말은 한 칸 더 전진합니다.
* 검정색 말을 2번 열과 3번 열에 올린 채로 (2,3), (4,5)를 이동시키고자 합니다. 이 경우, 5번 열과 9번 열 중 하나만 골라 검정색 말을 올리게 됩니다.
* 검정색 말을 2번, 3번, 12번 열에 올린채로 눈금 2, 3, 4, 5를 얻었습니다. 이 경우, 어떤 조합을 하든 눈금을 움직일 수 없으며, 강제로 턴을 잃게 됩니다. ('''턴 종료'''를 참조하세요.)
===턴 종료===
턴 종료는 크게 2가지 경우로 나뉩니다. 첫번째는 플레이어가 자의로 턴을 종료하는 경우이고, 두번째는 위의 예시처럼 어떻게 해도 말을 움직일 수 없는 경우입니다.
* 턴을 자의로 종료한 경우, 현재 검정색 말의 위치에 자신의 색깔 말을 올립니다. 이미 그 열에 자신의 말이 있다면 해당 위치로 올립니다.
* 턴을 강제로 종료당한 경우, 현재 검정색 말을 그대로 치웁니다. 즉, 이번 턴의 행동을 모두 잃게 됩니다.
Examples:
* 7번 열에서 3칸, 8번 열에서 2칸, 9번 열에서 1칸을 전진하고 턴을 자의로 종료했습니다. 만일 이 플레이어가 이전에 7번 열에서 4칸을 전진했었다면, 턴 종료 후 7번 열에서 7칸 앞에 있게 되는 것입니다. 나머지 열도 그대로 전진합니다.
* 7번 열에서 3칸, 8번 열에서 2칸, 9번 열에서 1칸을 전진하고 턴을 강제로 종료했습니다. 만일 이 플레이어가 이전에 7번 열에서 4칸을 전진했었다면, 턴 종료 후 7번 열에서 4칸을 유지하게 됩니다. 나머지 열의 진행 상황도 유지됩니다.
===열의 완성 (점수 득점)===
한 플레이어가 어느 열의 끝인 골인 지점에 도달한 후 자의로 턴을 종료한다면, 그 플레이어가 해당 열을 점령합니다. 해당 열은 그 플레이어의 차지가 되며, 해당 플레이어는 1점을 획득합니다. 더 이상 그 열은 전진에 사용될 수 없습니다.
===승리 조건===
가장 먼저 3점을 획득하면 승리합니다.
==기본 전략==
기본적으로 이 게임은 언제 멈춰야 하는지에 모든 것이 달려있습니다. 주사위 운으로 3점을 한 턴만에 따내고 승리하는 경우는 없다시피 하며, 그렇기 때문에 강제로 모든 전진을 날리기 전에 턴을 멈추는 것이 중요합니다. 다만, 너무 적게 전진할 경우 다른 플레이어가 자신을 역전할 수도 있으므로, 언제 멈출 지를 고민하는 것이 중요합니다.
7의 경우 총 6가지 경우의 수가 있지만, 2나 12같은 경우 1가지 경우의 수밖에 없습니다. 그렇기 때문에 2번 열과 12번의 열의 길이는 7번 열의 길이에 비해 짧습니다. 이를 참고하여 중앙을 점령할지, 아니면 양 옆을 점령할지에 따라 전략이 나뉠 수도 있습니다.
a50f7a54d6b43a49b8de9b4272df95bf60a4628b
Gamehelprollingpins
0
260
1482
2023-09-05T08:56:57Z
Unidaddykun
9162
새 문서: 개요 주사위 1개 또는 2개를 굴린 다음 총합과 동일한 핀에 줄을 그어 지웁니다(예: 5이면 2와 3 또는 4와 1을 지울 수 있습니다). 유효한 X 표시를 할 수 없을 때까지 계속 굴립니다. (예: 4를 사용하면 3과 1을 X로 표시하지만 마지막 예에서 3이 사용되었으므로 멈춰야 합니다.) 그런 다음 두 번째 롤 단계를 시작하지만 동일한 X 표시 핀을 유지합니다. 두 번째 굴림에...
wikitext
text/x-wiki
개요
주사위 1개 또는 2개를 굴린 다음 총합과 동일한 핀에 줄을 그어 지웁니다(예: 5이면 2와 3 또는 4와 1을 지울 수 있습니다).
유효한 X 표시를 할 수 없을 때까지 계속 굴립니다. (예: 4를 사용하면 3과 1을 X로 표시하지만 마지막 예에서 3이 사용되었으므로 멈춰야 합니다.)
그런 다음 두 번째 롤 단계를 시작하지만 동일한 X 표시 핀을 유지합니다.
두 번째 굴림에서 유효한 교차를 할 수 없으면 차례가 종료됩니다.
채점
한 차례에 교차된 핀의 수에 따라 점수를 매깁니다.
보너스 2개가 지급됩니다
a) 2번 공으로 10개의 핀을 모두 제거하면 10점 + 다음 첫 번째 시도의 점수가 됩니다.
b) 1번 공으로 10개의 핀을 모두 제거하면 10점 + 다음 차례의 두 시도 점수가 더해집니다.
추가 도움
표시된 볼링 공을 클릭하면 현재 롤에서 1을 더하거나 뺄 수 있습니다.
5af26c8584a65f5b3e4fe349c453d25f90e7ff52
Gamehelpsplendor
0
261
1483
2023-10-11T06:42:13Z
Sso0125
9230
새 문서: 각 개발 카드 데크는 개별적으로 셔플된 다음 테이블 중간에 있는 열에 아래에서 위로 순서를 늘립니다(◯; ◯◯; ◯◯◯). 레벨별로 4장의 카드가 공개됩니다. 고귀한 타일은 섞여서 플레이어 플러스 1이 있는 만큼 많이 드러납니다(예: 4인 게임에 타일 5개). 나머지 타일은 게임에서 제거되므로 게임 중에는 사용되지 않습니다. 플레이어 2명: 골드를 제외한 각 보...
wikitext
text/x-wiki
각 개발 카드 데크는 개별적으로 셔플된 다음 테이블 중간에 있는 열에 아래에서 위로 순서를 늘립니다(◯; ◯◯; ◯◯◯).
레벨별로 4장의 카드가 공개됩니다.
고귀한 타일은 섞여서 플레이어 플러스 1이 있는 만큼 많이 드러납니다(예: 4인 게임에 타일 5개).
나머지 타일은 게임에서 제거되므로 게임 중에는 사용되지 않습니다.
플레이어 2명: 골드를 제외한 각 보석 색상의 토큰 3개를 제거합니다(각 4개만 남아 있어야 함).
3명으로: 골드를 제외한 각 보석 색상의 토큰 2개를 제거합니다(각 5개만 남아 있어야 함).
게임 플레이
그런 다음 시계 방향으로 재생이 진행됩니다.
플레이어는 다음 네 가지 동작 중 하나만 수행하도록 선택해야 합니다.
• 색깔이 다른 보석 토큰 3개를 가져가세요.
• 같은 색의 보석 토큰 2개를 가져가세요. 이 동작은 플레이어가 가져갈 때 선택한 색의 토큰이 최소 4개 이상 남아 있을 경우에만 가능합니다.
• 개발 카드 1장 예약 후 골드토큰 1장 가져가세요.
• 테이블 중간에서 페이스업 개발 카드 1장 또는 기존에 예약한 카드를 구매합니다.
토큰 선택
플레이어는 자신의 순서가 끝날 때마다 10개 이상의 토큰을 가질 수 없습니다(조커 포함). 만약 이런 일이 발생하면 10개만 남을 때까지 토큰을 반환해야 합니다. 플레이어는 방금 그린 것의 전부 또는 일부를 반환할 수 있습니다
개발 카드 예약
카드를 예약하려면 플레이어가 테이블 중간에서 얼굴을 위로 향하게 하거나 다른 플레이어에게 카드를 보여주지 않고 세 덱(레벨 ◯; ◯◯; ◯◯◯) 중 하나에서 첫 번째 카드를 꺼내기만 하면 됩니다.
예약된 카드는 소지하고 있기 때문에 폐기할 수 없습니다.
플레이어는 예약된 카드를 세 장 이상 가지고 있지 않을 수 있으며, 카드를 없애는 유일한 방법은 카드를 사는 것입니다.
카드를 예약하는 것도 골드토큰(조커)을 얻을 수 있는 유일한 방법이며, 골드가 남아있지 않으면 카드를 예약할 수 있지만 골드를 받을 수 없습니다.
a4e7bdec6cb440fc71a09fe20c84b86d12480a75
대문
0
175
1484
1298
2023-10-15T14:44:10Z
Nilzzzzy
7482
/* Games */
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpabandonallartichokes|아티초크 버리기]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
</td>
<td valign="top">
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpincangold|Incangold]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
</td>
<td valign="top">
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
</td>
<td valign="top">
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
7aff62102b73e93fb8e779b8b06c1bf94448a716
1486
1484
2023-10-15T15:24:22Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpabandonallartichokes|아티초크 버리기]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpincangold|잉카의 황금]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
</td>
<td valign="top">
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
</td>
<td valign="top">
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
</td>
<td valign="top">
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
b24876f88d3c79c8f29f14b379be7e6b78aafa27
1487
1486
2023-10-15T15:25:17Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpabandonallartichokes|아티초크 버리기]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpincangold|잉카의 황금]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
</td>
<td valign="top">
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
</td>
<td valign="top">
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
</td>
<td valign="top">
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
966e2c3bec8f2f58b22f0cc1c6835fd572a5bde3
1488
1487
2023-10-15T15:28:53Z
Nilzzzzy
7482
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpabandonallartichokes|아티초크 버리기]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpincangold|잉카의 황금]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
</td>
<td valign="top">
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
</td>
<td valign="top">
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
</td>
<td valign="top">
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
</td>
<td valign="top">
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
</td>
<td valign="top">
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
</td>
<td valign="top">
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
</td>
<td valign="top">
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
</td>
<td valign="top">
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
</td>
<td valign="top">
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
5dc1ad2159c63e9f15a159f27d7baa3e7afa1731
1489
1488
2023-10-15T15:29:54Z
Nilzzzzy
7482
[[Special:Contributions/Nilzzzzy|Nilzzzzy]] ([[User talk:Nilzzzzy|토론]])의 1488판 편집을 되돌림
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpabandonallartichokes|아티초크 버리기]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpincangold|잉카의 황금]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
</td>
<td valign="top">
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
</td>
<td valign="top">
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
</td>
<td valign="top">
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
966e2c3bec8f2f58b22f0cc1c6835fd572a5bde3
1490
1489
2023-10-15T15:30:07Z
Nilzzzzy
7482
[[Special:Contributions/Nilzzzzy|Nilzzzzy]] ([[User talk:Nilzzzzy|토론]])의 1487판 편집을 되돌림
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpabandonallartichokes|아티초크 버리기]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpincangold|잉카의 황금]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
</td>
<td valign="top">
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
</td>
<td valign="top">
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
</td>
<td valign="top">
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
b24876f88d3c79c8f29f14b379be7e6b78aafa27
Gamehelpincangold
0
179
1485
1235
2023-10-15T15:22:26Z
Nilzzzzy
7482
이게 제일 깔끔하게 정리한것이라고 생각합니다
wikitext
text/x-wiki
== 개요 ==
계속 탐험할지 말지 선택에 따라 점수를 얻는 탐험 게임입니다.
== 구성품==
* 보물 카드 14장 (1, 2, 3, 4, 5, 5, 7, 7, 9, 11, 11, 13, 14, 15 개의 보석)
* 위험 카드 15장(화재, 미라, 바위, 뱀, 거미 각각 3 개)
* 유물 카드 5장
== 진행 ==
게임은 총 5라운드로 진행됩니다.
각 라운드 마다 보물 카드 14장, 위험카드 15장, 유물카드 중의 한장을 섞어 모험 카드 더미를 만듭니다.
라운드가 시작되면 모든 플레이어가 탐사를 시작하며, 매 턴마다 아래의 순서대로 진행됩니다.
1. 모험 카드 더미에서 카드를 한 장 공개합니다.
2-1. 보물 카드가 공개되었다면 보석을 공평하게 분배하고 남는 보석은 분배하지 않습니다.
13의 보물 카드가 공개되었을 때 5명의 플레이어가 탐사를 진행하고 있었다면 각자 2개의 보석을 분배받고 3개는 분배하지 않습니다.
2-2. 위험 카드가 공개되었다면 아무일도 일어나지 않습니다. 다만 이전에 같은 위험카드가 공개되었다면 모든 보물을 잃은 채 라운드가 종료되고 다음 라운드 시작시 해당 종류의 위험카드를 한장 제거합니다.
2-3. 유물 카드가 공개되었다면 아무일도 일어나지 않습니다.
3. 탐사를 계속 진행할지를 결정합니다.
3-1. 탐사를 그만두기로 결정하였다면 그만두기로 결정한 플레이어들끼리 분배되지 않은 보석을 분배합니다. 혼자 탐사를 그만두기로 결정하였다면 보물 카드도 가져갈 수 있습니다.
3-2. 탐사를 그만둔 시점에서 가져온 보석 1개당 1점으로 변환합니다. 유물 카드는 5점으로 변환합니다.
점수는 자기 자신의 것만 알 수 있습니다. 다른 플레이어의 점수는 직접 계산해야합니다.
3-3. 모든 플레이어가 탐사를 그만두었다면 라운드가 종료됩니다.
== 순위 ==
5라운드 종료 시점에서 점수가 많은 순으로 순위가 정해집니다.
동점일 시, 유물의 갯수가 가장 많은 순서대로 순위가 정해집니다.
유물의 갯수도 동일할 경우 순위가 동일합니다.
fcc7640581a6a455b76b17190a46d955c2d3e1b4
Gamehelpyatzy
0
122
1491
1389
2023-10-23T14:58:38Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 개요 ==
야찌는 각 턴마다 주사위를 굴려 '''포커'''처럼 족보를 만들어 점수를 얻어 경쟁하는 게임입니다.
== 진행 ==
매턴 마다 5개의 주사위를 굴립니다. 이후 원하는 주사위들을 최대 2번까지 더 굴릴 수 있습니다.
확정된 주사위를 아래의 족보에 따라 점수를 기입합니다. 각 영역에는 한번만 기입할 수 있습니다. 0점을 기입할 수도 있습니다.
규칙에 따라 기입할 수 있는 족보가 달라집니다.
== 규칙 ==
=== 야찌 ===
==== 상단 ====
상단에는 하나부터 여섯까지 족보가 있습니다. 주사위에서 해당 숫자의 눈금의 합을 점수로 계산합니다.
예를 들어, 2/6/3/4/6 조합으로는 여섯 칸에 12점을 기입할 수 있습니다.
상단에서 63점 이상을 내면 35점의 보너스 점수를 얻게됩니다. 보너스 점수가 중요한 야찌에서는 이것을 얻기 위해 각 주사위가 3개 이상이 되도록 하여 상단에 점수를 기입합니다.
==== 하단 ====
하단에는 아래와 같은 족보가 있습니다.
* 같은 숫자 3개 : 같은 숫자를 가진 주사위가 3개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 같은 숫자 4개 : 같은 숫자를 가진 주사위가 4개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 풀하우스 : 동일한 주사위 눈 한 종류가 3개, 다른 종류가 2개이거나 동일한 주사위 눈이 5개일 때, 25점을 기입합니다.
* 스몰 스트레이트 : 4개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4, 2/3/4/5, 3/4/5/6
* 라지 스트레이트 : 5개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4/5, 2/3/4/5/6
* 야찌 : 동일한 주사위 눈이 5개일 때, 50점을 기입합니다. 게임에서 야찌가 추가적으로 나올 때마다 보너스 점수 100점을 얻습니다.
* 찬스 : 조건 없이 모든 주사위 숫자 합계를 점수로 기입합니다. 족보를 완성하기 어려운 야찌에서 찬스를 이용해서 어려운 족보에 도전하는 것도 중요합니다.
c31a14a99965ace92aa8ae459773391047ad3364
1492
1491
2023-10-23T15:01:05Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 개요 ==
야찌는 각 턴마다 주사위를 굴려 '''포커'''처럼 족보를 만들어 점수를 얻어 경쟁하는 게임입니다.
== 진행 ==
매턴 마다 5개의 주사위를 굴립니다. 이후 원하는 주사위들을 최대 2번까지 더 굴릴 수 있습니다.
확정된 주사위를 아래의 족보에 따라 점수를 기입합니다. 각 영역에는 한번만 기입할 수 있습니다. 0점을 기입할 수도 있습니다.
규칙에 따라 기입할 수 있는 족보가 달라집니다.
== 규칙 ==
=== 야찌 ==='
가장 기본이 되는 규칙입니다. 다른 곳에서 이 게임을 진행할 시 점수 계산이 다를 수 있습니다.
==== 상단 ====
상단에는 하나부터 여섯까지 족보가 있습니다. 주사위에서 해당 숫자의 눈금의 합을 점수로 계산합니다.
예를 들어, 2/6/3/4/6 조합으로는 여섯 칸에 12점을 기입할 수 있습니다.
상단에서 63점 이상을 내면 35점의 보너스 점수를 얻게됩니다. 보너스 점수가 중요한 야찌에서는 이것을 얻기 위해 각 주사위가 3개 이상이 되도록 하여 상단에 점수를 기입합니다.
==== 하단 ====
하단에는 아래와 같은 족보가 있습니다.
* 같은 숫자 3개 : 같은 숫자를 가진 주사위가 3개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 같은 숫자 4개 : 같은 숫자를 가진 주사위가 4개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 풀하우스 : 동일한 주사위 눈 한 종류가 3개, 다른 종류가 2개이거나 동일한 주사위 눈이 5개일 때, 25점을 기입합니다.
* 스몰 스트레이트 : 4개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4, 2/3/4/5, 3/4/5/6
* 라지 스트레이트 : 5개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4/5, 2/3/4/5/6
* 야찌 : 동일한 주사위 눈이 5개일 때, 50점을 기입합니다. 게임에서 야찌가 추가적으로 나올 때마다 보너스 점수 100점을 얻습니다.
* 찬스 : 조건 없이 모든 주사위 숫자 합계를 점수로 기입합니다. 족보를 완성하기 어려운 야찌에서 찬스를 이용해서 어려운 족보에 도전하는 것도 중요합니다.
=== 얌 ===
=== 요트 ===
=== 얏찌 ===
=== 막시 얏찌 ===
=== 크래그 ===
5d7d06fdc7add34311abe0bf41ceff610d6c5173
1493
1492
2023-10-23T15:04:08Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 개요 ==
야찌는 각 턴마다 주사위를 굴려 '''포커'''처럼 족보를 만들어 점수를 얻어 경쟁하는 게임입니다.
== 진행 ==
매턴 마다 5개의 주사위를 굴립니다. 이후 원하는 주사위들을 최대 2번까지 더 굴릴 수 있습니다.
확정된 주사위를 아래의 족보에 따라 점수를 기입합니다. 각 영역에는 한번만 기입할 수 있습니다. 0점을 기입할 수도 있습니다.
규칙에 따라 기입할 수 있는 족보가 달라집니다.
== 규칙 ==
=== 야찌 ===
가장 기본이 되는 규칙입니다. 다른 곳에서 이 게임을 진행할 시 점수 계산이 다를 수 있습니다.
==== 상단 ====
상단에는 하나부터 여섯까지 족보가 있습니다. 주사위에서 해당 숫자의 눈금의 합을 점수로 계산합니다.
예를 들어, 2/6/3/4/6 조합으로는 여섯 칸에 12점을 기입할 수 있습니다.
상단에서 63점 이상을 내면 35점의 보너스 점수를 얻게됩니다. 보너스 점수가 중요한 야찌에서는 이것을 얻기 위해 각 주사위가 3개 이상이 되도록 하여 상단에 점수를 기입합니다.
==== 하단 ====
하단에는 아래와 같은 족보가 있습니다.
* 같은 숫자 3개 : 같은 숫자를 가진 주사위가 3개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 같은 숫자 4개 : 같은 숫자를 가진 주사위가 4개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 풀하우스 : 동일한 주사위 눈 한 종류가 3개, 다른 종류가 2개이거나 동일한 주사위 눈이 5개일 때, 25점을 기입합니다.
* 스몰 스트레이트 : 4개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4, 2/3/4/5, 3/4/5/6
* 라지 스트레이트 : 5개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4/5, 2/3/4/5/6
* 야찌 : 동일한 주사위 눈이 5개일 때, 50점을 기입합니다. 게임에서 야찌가 추가적으로 나올 때마다 보너스 점수 100점을 얻습니다.
* 찬스 : 조건 없이 모든 주사위 숫자 합계를 점수로 기입합니다. 족보를 완성하기 어려운 야찌에서 찬스를 이용해서 어려운 족보에 도전하는 것도 중요합니다.
=== 얌 ===
=== 요트 ===
=== 얏찌 ===
=== 막시 얏찌 ===
=== 크래그 ===
247ce8ac1888b45b94be32b40a810cae93d8b31e
Gamehelpsimilo
0
262
1494
2023-10-26T10:50:42Z
Nyangto
9271
새 문서: [목표] Similo는 모든 플레이어가 비밀 캐릭터를 식별(선택이 아닌)하여 승리하는 협동 게임입니다. [준비] 이 게임에서 한 명의 플레이어는 단서 제공자 역할을 하고, 다른 플레이어들은 추측자 역할을 합니다. 단서 제공자는 5장의 카드로 시작합니다. 3x4 그리드 형식의 카드들이 배포되고, 카드 한장이 비밀 캐릭터로 강조 표시됩니다. (이때의 정보는 단서 제공자...
wikitext
text/x-wiki
[목표]
Similo는 모든 플레이어가 비밀 캐릭터를 식별(선택이 아닌)하여 승리하는 협동 게임입니다.
[준비]
이 게임에서 한 명의 플레이어는 단서 제공자 역할을 하고, 다른 플레이어들은 추측자 역할을 합니다.
단서 제공자는 5장의 카드로 시작합니다.
3x4 그리드 형식의 카드들이 배포되고, 카드 한장이 비밀 캐릭터로 강조 표시됩니다. (이때의 정보는 단서 제공자에게만 공개됩니다.)
[게임 플레이]
게임은 5개의 라운드로 구성됩니다.
각 라운드의 시작에서, 단서 제공자는 손에서 한 장의 카드를 선택합니다.
그리고 선택한 카드를 수직 또는 수평으로 놓습니다.
(중요!) 이때, 수직은 비밀 카드의 비밀 캐릭터와 "비슷한 것"이 있다는 것을 알리기 위한 행동이며
수평으로 놓은 경우 비밀 카드의 비밀 캐릭터와 "다른 것"이 있다는 것을 알리기 위한 행동입니다.
그런 다음 그는 한 장의 카드를 뽑습니다.
이후, 추측자들은 함께 논의를 진행하고, 어떤 카드들이 비밀 캐릭터를 나타내지 않는지 결정합니다.
그런 다음, 카드 그리드에서 일정 수의 카드를 제거합니다.
제거되는 카드 수는 라운드마다 증가하며, 첫 번째 라운드에는 1장, 두 번째 라운드에는 2장, 세 번째 라운드에는 3장, 네 번째 라운드에는 4장, 마지막 라운드에는 다시 1장이 제거됩니다.
제거된 카드가 비밀 캐릭터가 아닌 경우, 다음 라운드로 진행합니다.
그러나 만약 비밀 캐릭터가 제거되었다면 게임이 종료됩니다.
[게임 종료]
게임은 두 가지 가능한 결과가 있습니다.
추측자들이 게임 중 어떤 시점에서든 비밀 캐릭터를 실수로 제거하면, 모든 플레이어가 패배합니다.
마지막 라운드에서, 남아 있는 마지막 카드가 비밀 캐릭터로 정확하게 식별된다면, 모든 플레이어가 승리합니다.
96a4487c700f1cda02a90ad84f9dcb5d87494c23
Gamehelpseotda
0
237
1495
1425
2023-11-03T08:42:40Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
7e1e678ee18a2b0995b4e109fc330f18458c78c4
1496
1495
2023-11-03T08:46:14Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
d92185977089f8454bd0f38dd226e4ec1dfc28f0
1497
1496
2023-11-03T08:46:25Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
75353b67338d1966ed5ad2304e43dd9641bd46e2
1498
1497
2023-11-03T08:49:04Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
[[분류:카드 게임]]
69120bfe0c1e08f567a919aefdb5cfab5d7c1140
1501
1498
2023-11-03T09:00:09Z
Nilzzzzy
7482
/* 족보 */
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
{| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;"
|-
! |
|| 광봉 || 1광 + 3광 + 8광
|-
! |
|| 고도리 || 2열끗 + 4열끗 + 8열끗
|-
! | 3장 족보 || 홍단 || 1띠 +2띠 + 3띠
|-
! |
|| 청단 || 6띠 + 9띠 + 10띠
|-
! |
|| 초단 || 4띠 + 5띠 + 7띠
|-
! | Points
| 11 ||
|}
[[분류:카드 게임]]
496c2139de3937d9965275a07e2027296574775e
Browser support
0
13
1499
969
2023-11-03T08:49:55Z
Nilzzzzy
7482
wikitext
text/x-wiki
<h3>For the best experience, we recommend:</h3>
* '''Google Chrome 10+''' [http://www.google.com/chrome Windows] [http://www.google.com/chrome?platform=mac Mac] [http://www.google.com/chrome?platform=linux Linux]
* '''Mozilla Firefox 4+''' [http://www.mozilla.org/products/firefox/ Windows] [http://www.mozilla.org/products/firefox/ Mac] [http://www.mozilla.org/products/firefox/ Linux]
Board Game Arena takes advantage of the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download or update, no plugins to install, etc.
Consequently, to play you need to use a modern web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be.
This website makes intensive use of Javascript and your browser's graphics capabilities. Thus, if you want to have the best gaming experience with Board Game Arena, you should use one of the browsers listed above. However, we officially support the following browsers:
* Google Chrome 4+
* Mozilla Firefox 3.5+
* Internet Explorer 9+
* Safari 4+
(Note: We do NOT support playing on iPads or similar tablets.)
[[분류:Help]]
ffa637e43a52dd2cb0e54d13a8f3a9e2a8ed0cd3
분류:카드 게임
14
263
1500
2023-11-03T08:50:47Z
Nilzzzzy
7482
새 문서: 카드를 이용한 보드 게임
wikitext
text/x-wiki
카드를 이용한 보드 게임
b2111b4a07e1d9038964ed09d3d91e0094a426c2
Gamehelpseotda
0
237
1502
1501
2023-11-03T09:03:22Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
{| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;"
|-
! |
|| 광봉 || 1광 + 3광 + 8광
|-
! |
|| 고도리 || 2열끗 + 4열끗 + 8열끗
|-
! | 3장 족보 || 홍단 || 1띠 +2띠 + 3띠
|-
! |
|| 청단 || 6띠 + 9띠 + 10띠
|-
! |
|| 초단 || 4띠 + 5띠 + 7띠
|-
! |
|| 광때 || 1광, 3광, 8광 중 2장
|-
! |
|| 땡 || 같은 월패 2장
|-
! | 2장 족보 || 알리 || 1월 + 2월
|-
! |
|| 독사 || 1월 + 4월
|-
! |
|| 구삥 || 1월 + 9월
|-
! |
|| 장삥 || 1월 + 10월
|-
! |
|| 장사 || 4월 + 10월
|-
! |
|| 세륙 || 4월 + 6월
|-
! |
|| 끗 || 어느 족보에도 해당하지 않을 때 두 장의 카드의 월을 더했을 때 1의 자리수. 9끗이 제일 높으며 0끗이 제일 낮다.
|}
[[분류:카드 게임]]
6c1667e034eb6652c0b9a69b40e2d09c4636dca3
1503
1502
2023-11-03T09:04:11Z
Nilzzzzy
7482
/* 족보 */
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
{| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;"
|-
! | 3장 족보 ||
|| 광봉 || 1광 + 3광 + 8광
|-
! | 3장 족보 ||
|| 고도리 || 2열끗 + 4열끗 + 8열끗
|-
! | 3장 족보 || 홍단 || 1띠 +2띠 + 3띠
|-
! | 3장 족보 ||
|| 청단 || 6띠 + 9띠 + 10띠
|-
! | 3장 족보 ||
|| 초단 || 4띠 + 5띠 + 7띠
|-
! | 2장 족보 ||
|| 광땡 || 1광, 3광, 8광 중 2장
|-
! | 2장 족보 ||
|| 땡 || 같은 월패 2장
|-
! | 2장 족보 || 알리 || 1월 + 2월
|-
! | 2장 족보 ||
|| 독사 || 1월 + 4월
|-
! | 2장 족보 ||
|| 구삥 || 1월 + 9월
|-
! | 2장 족보 ||
|| 장삥 || 1월 + 10월
|-
! | 2장 족보 ||
|| 장사 || 4월 + 10월
|-
! | 2장 족보 ||
|| 세륙 || 4월 + 6월
|-
! | 2장 족보 ||
|| 끗 || 어느 족보에도 해당하지 않을 때 두 장의 카드의 월을 더했을 때 1의 자리수. 9끗이 제일 높으며 0끗이 제일 낮다.
|}
[[분류:카드 게임]]
82d7195af5e1fc4111ec5a776b625bd26b11795a
1504
1503
2023-11-03T09:04:57Z
Nilzzzzy
7482
/* 족보 */
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
{| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;"
|-
! | 3장 족보 || 광봉 || 1광 + 3광 + 8광
|-
! | 3장 족보 || 고도리 || 2열끗 + 4열끗 + 8열끗
|-
! | 3장 족보 || 홍단 || 1띠 +2띠 + 3띠
|-
! | 3장 족보 || 청단 || 6띠 + 9띠 + 10띠
|-
! | 3장 족보 || 초단 || 4띠 + 5띠 + 7띠
|-
! | 2장 족보 || 광땡 || 1광, 3광, 8광 중 2장
|-
! | 2장 족보 || 땡 || 같은 월패 2장
|-
! | 2장 족보 || 알리 || 1월 + 2월
|-
! | 2장 족보 || 독사 || 1월 + 4월
|-
! | 2장 족보 || 구삥 || 1월 + 9월
|-
! | 2장 족보 || 장삥 || 1월 + 10월
|-
! | 2장 족보 || 장사 || 4월 + 10월
|-
! | 2장 족보 || 세륙 || 4월 + 6월
|-
! | 2장 족보 || 끗 || 어느 족보에도 해당하지 않을 때 두 장의 카드의 월을 더했을 때 1의 자리수. 9끗이 제일 높으며 0끗이 제일 낮다.
|}
[[분류:카드 게임]]
b143d33183795025091732f4d3ee6ea93e123d37
1505
1504
2023-11-03T09:08:48Z
Nilzzzzy
7482
/* 족보 */
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
{| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;"
|-
! | 3장 족보 || 광봉 || 1광 + 3광 + 8광
|-
! | 3장 족보 || 고도리 || 2열끗 + 4열끗 + 8열끗
|-
! | 3장 족보 || 홍단 || 1띠 +2띠 + 3띠
|-
! | 3장 족보 || 청단 || 6띠 + 9띠 + 10띠
|-
! | 3장 족보 || 초단 || 4띠 + 5띠 + 7띠
|-
! | 2장 족보 || 광땡 || 1광, 3광, 8광 중 2장
|-
! | 2장 족보 || 땡 || 같은 월패 2장
|-
! | 2장 족보 || 알리 || 1월 + 2월
|-
! | 2장 족보 || 독사 || 1월 + 4월
|-
! | 2장 족보 || 구삥 || 1월 + 9월
|-
! | 2장 족보 || 장삥 || 1월 + 10월
|-
! | 2장 족보 || 장사 || 4월 + 10월
|-
! | 2장 족보 || 세륙 || 4월 + 6월
|-
! | 2장 족보 || 끗 || 어느 족보에도 해당하지 않을 때 두 장의 카드의 월을 더했을 때 1의 자리수.
9끗이 제일 높으며 0끗이 제일 낮다.
|-
! | 2장 특수족보 || 구사 || 4월 + 9월
땡 미만까지 재대결
|-
! | 2장 특수족보 || 멍텅구리 구사 || 4열끗 + 9열끗
장땡 미만까지 재대결
|-
! | 2장 특수족보 || 땡잡이 || 3광 + 7열끗
장땡을 제외한 땡 상대로 승리, 상대가 그 외의 족보를 가졌을 경우 0끗으로 처리
|-
! | 2장 특수족보 || 암행어사 || 4열끗 | 7열끗
38광떙을 제외한 광떙 상대로 승리, 상대가 그 외의 족보를 가졌을 경우 1끗으로 처리
|}
[[분류:카드 게임]]
9bd17e1783a2a80b9e5370c1b275896ef9051cfc
1506
1505
2023-11-03T09:09:01Z
Nilzzzzy
7482
/* 족보 */
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
{| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;"
|-
! | 3장 족보 || 광봉 || 1광 + 3광 + 8광
|-
! | 3장 족보 || 고도리 || 2열끗 + 4열끗 + 8열끗
|-
! | 3장 족보 || 홍단 || 1띠 +2띠 + 3띠
|-
! | 3장 족보 || 청단 || 6띠 + 9띠 + 10띠
|-
! | 3장 족보 || 초단 || 4띠 + 5띠 + 7띠
|-
! | 2장 족보 || 광땡 || 1광, 3광, 8광 중 2장
|-
! | 2장 족보 || 땡 || 같은 월패 2장
|-
! | 2장 족보 || 알리 || 1월 + 2월
|-
! | 2장 족보 || 독사 || 1월 + 4월
|-
! | 2장 족보 || 구삥 || 1월 + 9월
|-
! | 2장 족보 || 장삥 || 1월 + 10월
|-
! | 2장 족보 || 장사 || 4월 + 10월
|-
! | 2장 족보 || 세륙 || 4월 + 6월
|-
! | 2장 족보 || 끗 || 어느 족보에도 해당하지 않을 때 두 장의 카드의 월을 더했을 때 1의 자리수.
9끗이 제일 높으며 0끗이 제일 낮다.
|-
! | 2장 특수족보 || 구사 || 4월 + 9월
땡 미만까지 재대결
|-
! | 2장 특수족보 || 멍텅구리 구사 || 4열끗 + 9열끗
장땡 미만까지 재대결
|-
! | 2장 특수족보 || 땡잡이 || 3광 + 7열끗
장땡을 제외한 땡 상대로 승리, 상대가 그 외의 족보를 가졌을 경우 0끗으로 처리
|-
! | 2장 특수족보 || 암행어사 || 4열끗 + 7열끗
38광떙을 제외한 광떙 상대로 승리, 상대가 그 외의 족보를 가졌을 경우 1끗으로 처리
|}
[[분류:카드 게임]]
9ad07a58780437ff431a81dc515d63a95f058925
1507
1506
2023-11-03T09:12:57Z
Nilzzzzy
7482
개발자 ufm이 이렇게 설정했다고 합니다.
wikitext
text/x-wiki
== 개요 ==
화투를 사용하는 카드 게임이다.
== 진행 ==
1. 모든 참가자들은 2장의 패를 확인하고 각자 한장씩 공개합니다.
2. 모두가 콜을 하거나 한명을 제외하고 모두 다이를 할 때까지 점수를 베팅합니다.
다이 : 참가비와 베팅에 사용한 점수를 모두 포기하고 해당 라운드에서 기권합니다.
콜 : 앞 사람이 베팅한 만큼과 동일한 점수를 냅니다.
체크 : 점수를 추가로 걸지 않고 순서를 넘깁니다. 선턴을 잡은 천번째 턴에만 가능합니다.
레이즈 : 앞 사람이 건 점수 보다 더 많은 점수를 냅니다.
3. 카드를 한장 더 받고 2의 과정을 진행합니다.
4. 카드의 족보가 더 높은 플레이어가 베팅된 점수를 모두 가져갑니다.
동일한 족보일 경우 동일한 족보를 가진 플레이어끼리 두장의 카드를 받고 재대결을 합니다.
== 족보 ==
아레나에서는 화면 오른쪽에 족보가 작성되어 있으며 위쪽으로 갈수록 높은 족보입니다.
{| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;"
|-
! | 3장 족보 || 광봉 || 1광 + 3광 + 8광
|-
! | 3장 족보 || 고도리 || 2열끗 + 4열끗 + 8열끗
|-
! | 3장 족보 || 홍단 || 1띠 +2띠 + 3띠
|-
! | 3장 족보 || 청단 || 6띠 + 9띠 + 10띠
|-
! | 3장 족보 || 초단 || 4띠 + 5띠 + 7띠
|-
! | 2장 족보 || 광땡 || 1광, 3광, 8광 중 2장
|-
! | 2장 족보 || 땡 || 같은 월패 2장
|-
! | 2장 족보 || 알리 || 1월 + 2월
|-
! | 2장 족보 || 독사 || 1월 + 4월
|-
! | 2장 족보 || 구삥 || 1월 + 9월
|-
! | 2장 족보 || 장삥 || 1월 + 10월
|-
! | 2장 족보 || 장사 || 4월 + 10월
|-
! | 2장 족보 || 세륙 || 4월 + 6월
|-
! | 2장 족보 || 끗 || 어느 족보에도 해당하지 않을 때 두 장의 카드의 월을 더했을 때 1의 자리수.
9끗이 제일 높으며 0끗이 제일 낮다.
|-
! | 2장 특수족보 || 구사 || 4월 + 9월
땡 미만까지 재대결
상대가 2끗 미만일 경우 3끗으로 처리
|-
! | 2장 특수족보 || 멍텅구리 구사 || 4열끗 + 9열끗
장땡 미만까지 재대결
상대가 2끗 미만일 경우 3끗으로 처리
|-
! | 2장 특수족보 || 땡잡이 || 3광 + 7열끗
장땡을 제외한 땡 상대로 승리, 상대가 그 외의 족보를 가졌을 경우 0끗으로 처리
|-
! | 2장 특수족보 || 암행어사 || 4열끗 + 7열끗
38광떙을 제외한 광떙 상대로 승리, 상대가 그 외의 족보를 가졌을 경우 1끗으로 처리
|}
[[분류:카드 게임]]
5a1c51961bc858904b1a123fe3bf282754428906
대문
0
175
1508
1490
2023-11-03T09:13:39Z
Nilzzzzy
7482
/* Games */
wikitext
text/x-wiki
아래의 게임 문서 목록은 편집 당시의 영어 위키(12/10 23:09)를 기준으로 한 것입니다. 한국어 번역이 완료된 경우에만 한국어 제목이 붙여지며, [[영어를 포함]]하여 다른 언어로 작성되어 있는 경우 해당 언어를 게임 이름 옆에 붙여주시길 바랍니다. (제작자나 권한이 있는 직업은 아니지만, 한국어 위키의 정돈을 위하여 위와 같이 작성하였습니다. 양해 부탁드립니다.)--[[사용자:Yooyou7|Yooyou7]] 2016년 12월 10일 (토) 15:12 (CET)
== Games ==
Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page.
<table cellpadding="0" cellspacing="5" border="0">
<tr>
<td valign="top">
'''플레이 가능'''
* [[Gamehelplama|라마]]
* [[Gamehelpseotda|섰다]]
* [[Gamehelpabandonallartichokes|아티초크 버리기]]
* [[Gamehelpyatzy|야찌]]
* [[Gamehelpgomoku|오목]]
* [[Gamehelpincangold|잉카의 황금]]
* [[Gamehelpsechsnimmt|젝스님트!]]
* [[Gamehelpcantstop|캔트 스탑]]
* [[Gamehelpkoikoi|코이코이]]
* [[Gamehelphearts|하트]]
* [[Gamehelpakeruption|화산 폭발]]
* [[Gamehelpeightmastersrevenge|8 Master's Revenge]]
* [[Gamehelpamyitis|Amyitis]]
* [[Gamehelparmadora|Armadöra]]
* [[Gamehelpassyria|Assyria]]
* [[Gamehelpbackgammon|Backgammon]]
* [[Gamehelpbattlesheep|Battle Sheep]]
* [[Gamehelpbattleoflits|Battle of LITS]]
* [[Gamehelpbelote|Belote]]
* [[Gamehelpbombay|Bombay]]
* [[Gamehelpcaylus|Caylus]]
* [[Gamehelpcheckers|Checkers]]
* [[Gamehelpchess|Chess]]
* [[Gamehelpchinagold|China Gold]]
* [[Gamehelpcinco|Cinco]]
* [[Gamehelpcolorpop|Color Pop]]
* [[Gamehelpcoloretto|Coloretto]]
* [[Gamehelpcoltexpress|Colt Express]]
</td>
<td valign="top">
* [[Gamehelpdarkagent|Dark Agent]]
* [[Gamehelpdiams|Diam's]]
* [[Gamehelpdragonline|Dragon Line]]
* [[Gamehelpdragonheart|Dragonheart]]
* [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]]
* [[Gamehelpflorenzacardgame|Florenza: The Card Game]]
* [[Gamehelpgearnpiston|Gear & Piston]]
* [[Gamehelpgosu|Gosu]]
* [[Gamehelpgyges|Gygès]]
* [[Gamehelphaggis|Haggis]]
* [[Gamehelphawaii|Hawaii]]
* [[Gamehelphanabi|Hanabi]]
* [[Gamehelpelfenland|Elfenland]]
* [[Gamehelphex|Hex]]
* [[Gamehelphive|Hive]]
* [[Gamehelpintheyearofthedragon|In the Year of the Dragon]]
* [[Gamehelpinjawara|Injawara]]
* [[Gamehelpjaipur|Jaipur]]
* [[Gamehelpk2|K2]]
* [[Gamehelpkahuna|Kahuna]]
* [[Gamehelpkalah|Kalah]]
* [[Gamehelpkeyflower|Keyflower]]
* [[Gamehelpkoryo|Koryŏ]]
* [[Gamehelpledernierpeuple|Le Dernier Peuple]]
</td>
<td valign="top">
* [[Gamehelplibertalia|Libertalia]]
* [[Gamehelplordsofxidit|Lords of Xidit]]
* [[Gamehelplostcities|Lost Cities]]
* [[Gamehelpmachiavelli|Machiavelli]]
* [[Gamehelpmetromania|Metromania]]
* [[Gamehelpmadeira|Madeira]]
* [[Gamehelpnautilus|Nautilus]]
* [[Gamehelpneutreeko|Neutreeko]]
* [[Gamehelpniagara|Niagara]]
* [[Gamehelpnoirkvi|Noir: Killer versus Inspector]]
* [[Gamehelpdudo|Perudo]]
* [[Gamehelppolis|Polis: Fight for the Hegemony]]
* [[Gamehelppuertorico|Puerto Rico]]
* [[Gamehelppylos|Pylos]]
* [[Gamehelpquarto|Quarto]]
* [[Gamehelpquantum|Quantum]]
* [[Gamehelpquoridor|Quoridor]]
* [[Gamehelpraceforthegalaxy|Race for the Galaxy]]
* [[Gamehelpreversi|Reversi]]
* [[Gamehelpsaboteur|Saboteur]]
* [[Gamehelpseasons|Seasons]]
* [[Gamehelpsenet|Senet]]
* [[Gamehelpsobek|Sobek]]
* [[Gamehelpspyrium|Spyrium]]
* [[Gamehelpstoneage|Stone Age]]
</td>
<td valign="top">
* [[Gamehelptakenoko|Takenoko]]
* [[Gamehelptargi|Targi]]
* [[Gamehelptashkalar|Tash-Kalar]]
* [[Gamehelptheboss|The Boss]]
* [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]]
* [[Gamehelpcarrara|The Palaces of Carrara]]
* [[Gamehelpthermopyles|Thermopyles]]
* [[Gamehelpthroughtheages|Through the Ages]]
* [[Gamehelptimemasters|Time Masters]]
* [[Gamehelptobago|Tobago]]
* [[Gamehelptokaido|Tokaido]]
* [[Gamehelptournay|Tournay]]
* [[Gamehelptroyes|Troyes]]
* [[Gamehelptwintinbots|Twin Tin Bots]]
* [[Gamehelptzolkin|Tzolk'in]]
* [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]]
* [[Gamehelpunitedsquare|United Square]]
* [[Gamehelpxiangqi|Xiangqi]]
</td>
<td valign="top">
'''삭제됨'''
* [[Gamehelpdominion|Dominion]]
</td>
</tr>
</table>
c776066f6eab8688d6b4e6c61e8877bb11360e33
Multipleaccounts
0
164
1509
1125
2023-11-05T16:39:55Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 주요 규칙 ==
'''한 사람당 BGA 계정 1개'''
== 같은 IP에서 플레이하기 ==
동일한 IP(인터넷 주소)를 사용하여 동일한 테이블에서 플레이하는 것이 '''인증된''' 것입니다.
"이 플레이어는 다른 플레이어와 같은 IP에서 플레이하고 있습니다." 라는 경고 메시지는 '''간단한 경고'''입니다. 이는 유용한 경고입니다. 왜냐하면 다른 플레이어들은 자신의 테이블에 게임 밖에서 논의할 수 있는 플레이어가 있다는 것을 알 권리가 있기 때문입니다.
다른 사람과 같은 인터넷 주소로 플레이하고 싶은 경우:
* 가장 좋은 선택은 같은 테이블에서 플레이 하지 않거나 지인들끼리 플레이하는 것입니다.
* 낯선 사람과 플레이하는 경우, 둘 이상의 서로 다른 사람이라는 사실을 인지시켜 그들을 편안하게 만드세요. 채팅방 밖에서 게임에 대해 논의하지 말고, 파트너와 협력(또는 킹메이킹)하지 마세요.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
== Boosting your ELO by playing against yourself ==
This is the most stupid and useless thing to do on BGA.
Why? Because this is very easy to detect, and because the penalty is:
* all your secondary account are removed.
* your primary account is reset to 1500 ELO for all games.
Why this is so easy to detect:
* When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO.
* In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game.
* In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account".
* Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless.
If you have a lot of time to spend, please try to get better at this game and please do not try to cheat.
4ffd69dc246d8e674bc20e5202f8368210fe09f0
1510
1509
2023-11-05T16:40:06Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 주요 규칙 ==
'''한 사람당 BGA 계정 1개'''
== 같은 IP에서 플레이하기 ==
동일한 IP(인터넷 주소)를 사용하여 동일한 테이블에서 플레이하는 것이 '''인증된''' 것입니다.
"이 플레이어는 다른 플레이어와 같은 IP에서 플레이하고 있습니다." 라는 경고 메시지는 '''간단한 경고'''입니다. 이는 유용한 경고입니다. 왜냐하면 다른 플레이어들은 자신의 테이블에 게임 밖에서 논의할 수 있는 플레이어가 있다는 것을 알 권리가 있기 때문입니다.
다른 사람과 같은 인터넷 주소로 플레이하고 싶은 경우:
* 가장 좋은 선택은 같은 테이블에서 플레이 하지 않거나 지인들끼리 플레이하는 것입니다.
* 낯선 사람과 플레이하는 경우, 둘 이상의 서로 다른 사람이라는 사실을 인지시켜 그들을 편안하게 만드세요. 채팅방 밖에서 게임에 대해 논의하지 말고, 파트너와 협력(또는 킹메이킹)하지 마세요.
When some of your opponents are playing from the same IP:
* You may refuse (politely) to play with them.
* You should probably be vigilant and check that they are not collaborating during the game.
* But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report.
== Boosting your ELO by playing against yourself ==
This is the most stupid and useless thing to do on BGA.
Why? Because this is very easy to detect, and because the penalty is:
* all your secondary account are removed.
* your primary account is reset to 1500 ELO for all games.
Why this is so easy to detect:
* When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO.
* In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game.
* In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account".
* Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless.
If you have a lot of time to spend, please try to get better at this game and please do not try to cheat.
73dd9cb508230f089155ec330d809b2229abe99a
Gamehelpthirtyone
0
264
1511
2023-11-10T10:56:06Z
Nilzzzzy
7482
새 문서: == 목표 == 2개의 여벌 목숨을 가지며 최후까지 살아남으십시오. == 점수 == === 동일한 모양 === 동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. === 동일한 숫자 === 동일한 숫자 3개가 모였을 때 30.5점으로 취급합니다. A 3장은 반드시 승리합니다. Losing Lives At the end of a round, any player who scored less than 21 points will lose a life From those with 2...
wikitext
text/x-wiki
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 점수 ==
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다.
=== 동일한 숫자 ===
동일한 숫자 3개가 모였을 때 30.5점으로 취급합니다. A 3장은 반드시 승리합니다.
Losing Lives
At the end of a round, any player who scored less than 21 points will lose a life
From those with 21 points or more, the lowest or tied lowest also loses a life
Turn
On your turn, you have 3 options
You can pass for the remainder of the round and keep the cards you have
You can swap 1 card in your hand with 1 of the central cards
You can exchange your hand for all the central cards
0ee07b9d543c7c0d7ffcd40d4224fe925a67f2c0
1512
1511
2023-11-10T11:11:40Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다.
== 점수 ==
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다.
=== 동일한 숫자 ===
동일한 숫자 3개가 모였을 때 30.5점으로 취급합니다. A 3장은 반드시 승리합니다.
== 승부 ==
점수를 계산하여 낮은 점수를 가진 사람이 목숨을 잃습니다. 여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
Turn
On your turn, you have 3 options
You can pass for the remainder of the round and keep the cards you have
You can swap 1 card in your hand with 1 of the central cards
You can exchange your hand for all the central cards
a7508987125cfa2710c824ebae94877f03a60ff1
1513
1512
2023-11-10T11:17:26Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱을 하면 상대는 라운드 스톱을 하여 승부를 내거나 카드 교환 후 승부를 내야합니다.
== 점수 ==
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다.
=== 동일한 숫자 ===
동일한 숫자 3개가 모였을 때 30.5점으로 취급합니다. A 3장은 반드시 승리합니다.
== 승부 ==
점수를 계산하여 낮은 점수를 가진 사람이 목숨을 잃습니다. 여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
61cc1a1b826be0e8f0f32a4ba26af58475967788
1514
1513
2023-11-10T11:19:40Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
== 점수 ==
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
동일한 숫자 3개가 모였을 때 30.5점으로 취급합니다. A 3장 완성시 이후의 모든 턴을 스킵하고 승리합니다.
== 승부 ==
점수를 계산하여 낮은 점수를 가진 사람이 목숨을 잃습니다. 여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
e93d0cb943cbb99e67aaf7207a3c379f5a96e8fe
1515
1514
2023-11-10T11:20:58Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
== 점수 ==
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
동일한 숫자 3개가 모였을 때 30.5점으로 취급합니다. A 3장 완성시 이후의 모든 턴을 스킵하고 승리합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다. 여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
9589a91c15e7dd45fb2d99e337fc6b7b37f1ddd8
1516
1515
2023-11-10T11:22:39Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
== 점수 ==
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
동일한 숫자 3개가 모였을 때 30.5점으로 취급합니다. A 3장 완성시 이후의 모든 턴을 스킵하고 승리합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다.
동점일 경우 라운드 스톱을 선언한 사람이 승리합니다.
여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
59ed6d6b8244a90b0228ac0bf96287f9d881f7b7
1517
1516
2023-11-10T11:25:59Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
== 점수 ==
누군가 31이나 불꽃을 완성하면 즉시 라운드가 종료됩니다.
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
트리플은 30.5점, 불꽃(A 트리플)은 32점으로 취급합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다.
동점일 경우 라운드 스톱을 선언한 사람이 승리합니다.
여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
d0359fed7c020a966dda079348a1a27b0eb8539c
1518
1517
2023-11-10T11:28:56Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
3. 카드 더미에 카드가 부족할 경우 마지막 차례를 진행합니다.
== 점수 ==
누군가 31이나 불꽃을 완성하면 즉시 라운드가 종료됩니다.
동점일 경우 라운드 스톱을 선언한 사람이 점수가 더 높은 것으로 취급합니다. 그 외의 경우 무늬로 승패를 가립니다.
2명 이상이 트리플일 경우, 더 높은 등급이 더 높은 것으로 취급합니다.
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
트리플은 30.5점, 불꽃(A 트리플)은 32점으로 취급합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다.
여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
8551709cc3c1b24b66b8a9bd7cecef3cbaa4640a
1519
1518
2023-11-10T18:06:12Z
Nilzzzzy
7482
wikitext
text/x-wiki
== 개요 ==
트럼프 카드를 사용하는 클래식 카드 게임이다.
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
3. 카드 더미에 카드가 부족할 경우 마지막 차례를 진행합니다.
== 점수 ==
누군가 31이나 불꽃을 완성하면 즉시 라운드가 종료됩니다.
동점일 경우 라운드 스톱을 선언한 사람이 점수가 더 높은 것으로 취급합니다. 그 외의 경우 무늬로 승패를 가립니다.
2명 이상이 트리플일 경우, 더 높은 등급이 더 높은 것으로 취급합니다.
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
트리플은 30.5점, 불꽃(A 트리플)은 32점으로 취급합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다.
여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
08874b2513ac09e17235b31cdb0f80aeb6fbe4c1
1520
1519
2023-11-12T23:12:35Z
Nilzzzzy
7482
/* 점수 */
wikitext
text/x-wiki
== 개요 ==
트럼프 카드를 사용하는 클래식 카드 게임이다.
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
3. 카드 더미에 카드가 부족할 경우 마지막 차례를 진행합니다.
== 점수 ==
누군가 31이나 불꽃을 완성하면 즉시 라운드가 종료됩니다.
동점일 경우 라운드 스톱을 선언한 사람이 점수가 더 높은 것으로 취급합니다. 그 외의 경우 무늬로 승패를 가립니다.(스다하클이 아닙니다. 현재 확인한 것은 클로버가 스페이드, 다이아를 이기고 하트가 다이아를 이깁니다.)
2명 이상이 트리플일 경우, 더 높은 등급이 더 높은 것으로 취급합니다.
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
트리플은 30.5점, 불꽃(A 트리플)은 32점으로 취급합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다.
여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
d1c80613111023a19401b33a58f1fae85e860056
Gamehelphanabi
0
265
1521
2023-11-18T05:10:01Z
Nilzzzzy
7482
새 문서: Hanabi is a cooperative game. Your goal, as a team, is to build a fabulous fireworks show. You have to put together 5 fireworks ( 1 white, 1 red, 1 blue, 1 yellow, 1 green), by making series rising in number (1, 2, 3, 4, 5) with the same coloured cards. However, you cannot see your own cards; you can only see the cards of your team mates. Also, communication (and non communication) between the players is essential to Hanabi. You can only communication with your teammates...
wikitext
text/x-wiki
Hanabi is a cooperative game. Your goal, as a team, is to build a fabulous fireworks show. You have to put together 5 fireworks ( 1 white, 1 red, 1 blue, 1 yellow, 1 green), by making series rising in number (1, 2, 3, 4, 5) with the same coloured cards.
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{|class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
|0-5
|horrible, booed by the crowd...
|-
|6-10
|mediocre, just a spattering of applause.
|-
|11-15
|honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
|21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
== Card distribution ==
* Each card has a colour and a number.
{|class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
=== Multicolour cards ===
* There are three variants that add a 6th colour: the multicolour.
* There are three difficulties:
==== Tricky ====
* These cards get marked by a separate '''multicolour clue'''.
{|class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==== Hard ====
* These cards get marked by a separate '''multicolour clue'''.
{|class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==== Very Difficult ====
* These cards get marked by '''any colour clue'''.
{|class="wikitable" style="width:auto;" border="2"
|+Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== Setup ==
* 8 clue tokens.
{|class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
== Game play ==
Players take turns to either:
• Give a '''clue'''<br/>
• '''Play''' a card, or<br/>
• '''Discard''' a card
=== Clue ===
* Possible when there is at least one clue token available.
* Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br/>
2. The active player selects a clue option.<br/>
3. One clue token is moved from 'available' to 'used'.
=== Play ===
1. The active player selects a card in their hand.<br/>
2. The active player selects the 'Play selected card' button.<br/>
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br/>
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br/>
3. A replacement card is drawn.
=== Discard ===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br/>
2. The active player selects the 'Discard selected card' button.<br/>
3. The discarded card is placed in the discard pile.<br/>
4. One clue token is moved from 'used' to 'available'.<br/>
5. A replacement card is drawn.
== Game end ==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
== Options ==
=== Black Powder ===
* Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{|class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
=== Five Flamboyants ===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
* Gain a clue token.
* Gain a clue token and recover a life.
* Give a clue regarding a colour.
* Give a clue regarding a number.
* Shuffle a discarded card into the deck.
* Play a discarded card, if possible.
== Lingo ==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked: A card that is highlighted by a clue.
;Unmarked: A card that is not clued.
;chop: The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw: The newest, unmarked card. The card that you have no information on and was freshly drawn.
;To bomb: A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique: A card that has no copy (left) in the deck.
;Double discard: When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop: 2 consecutive players have the same card on chop. Same as Double discard
;Double save: When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy: A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating ==
* If you are playing with ELO rating on, your ELO may be changed at the end of the game.
* Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
**• If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
* You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
* If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
* To be confirmed: I think the ELO-system has had an overhaul.
== Cheating ==
* Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
== Conventions ==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
* The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
* Many players have different kinds of conventions.
** ''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
* When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
** This is why there is an option to display the convention for the table.
** See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
* Ideally, all players adhere to the convention, to avoid miscommunication.
* Below, the meta-information of several conventions is explained.
=== Standard ===
* Players assume the following meta-information:
** Every marked card will be playable at some point.
==== Number clue ====
* Cards with a number-clue on them must be saved to be played later on in the game
* Saved cards can be safely played when all "number-1" cards are played.
** ''Saved cards are played from oldest to newest.''
==== Colour clue ====
* The newest, previously unmarked card, is the next playable card in the sequence.
* The oldest, unmarked card is safe to discard.
** If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
* A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
** e.g. Marking 4s in another hand if your hand could have a copy of that 4.
* Sometimes, a "bad" clue cannot be avoided.
** ''e.g. Save a unique 3 using a number clue which also marks unplayable cards.
** ''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.
* When a ''lie'' has been told, it needs to be corrected.
* A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
=== Finesse ===
* Finesse builds on the standard convention (making it a bit more complex).
* In the finesse convention, the timing of the clue gives you extra information.
* You can assume the following meta-information:
** Every card that gets marked, will be playable at some point.
** If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
** The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
*** ''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
** Clues are given by the last possible player.
*** When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
==== Special interpretations ====
* When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
* The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
* If a marked card gets discarded it means:
** The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
** The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
==== Clues you should avoid giving (bad clues) ====
* As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention ====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
* If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
* With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
===== a) Skipping / stealing should be avoided =====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
* If more than 1 person are able to give the same clue, then the last possible person should give that clue.
* In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
===== b) Skipping / stealing is for discard-management =====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
* Your chop-card is trash (a copy of the card is already played/marked)
* Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
* You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
* This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
* If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
* avoid twin-chops before they become an issue
* avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
=== Others conventions ===
* For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
== Strategy ==
* In addition to the convention(s), there is also some strategy to the game.
* You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
=== Examples ===
* More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
* It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
* Trying to mark at least 12 cards with the first 8 clue-tokens.
** This gives 99% chance of always having enough tokens in the game.
* Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
446752de29ffeaf2343c3b7021e8863153819612
1522
1521
2023-11-18T05:14:24Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
You have to put together 5 fireworks ( 1 white, 1 red, 1 blue, 1 yellow, 1 green), by making series rising in number (1, 2, 3, 4, 5) with the same coloured cards.
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{| class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
| 0-5
|horrible, booed by the crowd...
|-
| 6-10
|mediocre, just a spattering of applause.
|-
|11-15
| honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
| 21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
==Card distribution ==
*Each card has a colour and a number.
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
===Multicolour cards===
*There are three variants that add a 6th colour: the multicolour.
*There are three difficulties:
====Tricky ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Hard ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Very Difficult ====
*These cards get marked by '''any colour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+ Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==Setup==
*8 clue tokens.
{| class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
==Game play==
Players take turns to either:
• Give a '''clue'''<br />
• '''Play''' a card, or<br />
• '''Discard''' a card
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
aada9217256d335d57de03836779dc9d2c0c984a
1526
1522
2023-11-18T05:27:27Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
You have to put together 5 fireworks ( 1 white, 1 red, 1 blue, 1 yellow, 1 green), by making series rising in number (1, 2, 3, 4, 5) with the same coloured cards.
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{| class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
| 0-5
|horrible, booed by the crowd...
|-
| 6-10
|mediocre, just a spattering of applause.
|-
|11-15
| honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
| 21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
==Card distribution ==
*Each card has a colour and a number.
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
===Multicolour cards===
*There are three variants that add a 6th colour: the multicolour.
*There are three difficulties:
====Tricky ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Hard ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Very Difficult ====
*These cards get marked by '''any colour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+ Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==Setup==
*8 clue tokens.
{| class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
==Game play==
Players take turns to either:
• Give a '''clue'''<br />
• '''Play''' a card, or<br />
• '''Discard''' a card
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
82d06ddb8ab3e87fdd8f6b7620f7c0fba56ccdde
1529
1526
2023-11-18T05:29:35Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{Hcardr|=1|background=#324|colour=#d03|size=2}}{{Hcardr|=1|background=#324|colour=#d03|size=2}}{{Hcardr|=1|background=#324|colour=#d03|size=2}}
|{{Hcardr|=2|background=#324|colour=#d03|size=2}}{{Hcardr|=2|background=#324|colour=#d03|size=2}}
|{{Hcardr|=3|background=#324|colour=#d03|size=2}}{{Hcardr|=3|background=#324|colour=#d03|size=2}}
|{{Hcardr|=4|background=#324|colour=#d03|size=2}}{{Hcardr|=4|background=#324|colour=#d03|size=2}}
|{{Hcardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
You have to put together 5 fireworks ( 1 white, 1 red, 1 blue, 1 yellow, 1 green), by making series rising in number (1, 2, 3, 4, 5) with the same coloured cards.
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{| class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
| 0-5
|horrible, booed by the crowd...
|-
| 6-10
|mediocre, just a spattering of applause.
|-
|11-15
| honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
| 21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
==Card distribution ==
*Each card has a colour and a number.
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
===Multicolour cards===
*There are three variants that add a 6th colour: the multicolour.
*There are three difficulties:
====Tricky ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Hard ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Very Difficult ====
*These cards get marked by '''any colour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+ Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==Setup==
*8 clue tokens.
{| class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
==Game play==
Players take turns to either:
• Give a '''clue'''<br />
• '''Play''' a card, or<br />
• '''Discard''' a card
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
525d56159fd09d1b74ee4367f768e9208871f95f
1530
1529
2023-11-18T05:30:29Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
You have to put together 5 fireworks ( 1 white, 1 red, 1 blue, 1 yellow, 1 green), by making series rising in number (1, 2, 3, 4, 5) with the same coloured cards.
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{| class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
| 0-5
|horrible, booed by the crowd...
|-
| 6-10
|mediocre, just a spattering of applause.
|-
|11-15
| honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
| 21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
==Card distribution ==
*Each card has a colour and a number.
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
===Multicolour cards===
*There are three variants that add a 6th colour: the multicolour.
*There are three difficulties:
====Tricky ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Hard ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Very Difficult ====
*These cards get marked by '''any colour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+ Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==Setup==
*8 clue tokens.
{| class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
==Game play==
Players take turns to either:
• Give a '''clue'''<br />
• '''Play''' a card, or<br />
• '''Discard''' a card
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
68e7770a102b1891168ebc2ba064e9d040310b64
1534
1530
2023-11-18T05:34:05Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
You have to put together 5 fireworks ( 1 white, 1 red, 1 blue, 1 yellow, 1 green), by making series rising in number (1, 2, 3, 4, 5) with the same coloured cards.
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{| class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
| 0-5
|horrible, booed by the crowd...
|-
| 6-10
|mediocre, just a spattering of applause.
|-
|11-15
| honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
| 21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
==Card distribution ==
*Each card has a colour and a number.
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
===Multicolour cards===
*There are three variants that add a 6th colour: the multicolour.
*There are three difficulties:
====Tricky ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Hard ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Very Difficult ====
*These cards get marked by '''any colour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+ Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==Setup==
*8 clue tokens.
{| class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
==Game play==
Players take turns to either:
• Give a '''clue'''<br />
• '''Play''' a card, or<br />
• '''Discard''' a card
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
7dcda06e4de61c57980e93f0b0a79f185db8505b
1539
1534
2023-11-18T05:41:40Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!Red (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!Multicolour (m)
|{{Hcardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{Hcardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{Hcardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{Hcardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{Hcardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{Hcardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{Hcardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{Hcardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{Hcardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{Hcardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!Multi-colour (m)
|{{Hcardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{Hcardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{Hcardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{Hcardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{Hcardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{| class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
| 0-5
|horrible, booed by the crowd...
|-
| 6-10
|mediocre, just a spattering of applause.
|-
|11-15
| honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
| 21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
==Card distribution ==
*Each card has a colour and a number.
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
===Multicolour cards===
*There are three variants that add a 6th colour: the multicolour.
*There are three difficulties:
====Tricky ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Hard ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Very Difficult ====
*These cards get marked by '''any colour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+ Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==Setup==
*8 clue tokens.
{| class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
==Game play==
Players take turns to either:
• Give a '''clue'''<br />
• '''Play''' a card, or<br />
• '''Discard''' a card
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
4a61b03268c747fbda1b0cab66cf0a8a0161c51c
1540
1539
2023-11-18T05:42:30Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!Red (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!Multicolour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!Multi-colour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{| class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
| 0-5
|horrible, booed by the crowd...
|-
| 6-10
|mediocre, just a spattering of applause.
|-
|11-15
| honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
| 21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
==Card distribution ==
*Each card has a colour and a number.
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
===Multicolour cards===
*There are three variants that add a 6th colour: the multicolour.
*There are three difficulties:
====Tricky ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Hard ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Very Difficult ====
*These cards get marked by '''any colour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+ Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==Setup==
*8 clue tokens.
{| class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
==Game play==
Players take turns to either:
• Give a '''clue'''<br />
• '''Play''' a card, or<br />
• '''Discard''' a card
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
d8a1db7a2b10208712caaa69b17db3c34c46aec0
1541
1540
2023-11-18T05:48:15Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!Red (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!Multicolour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!Multi-colour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 단서 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
However, you cannot see your own cards; you can only see the cards of your team mates.
Also, communication (and non communication) between the players is essential to Hanabi.
You can only communication with your teammates when you give them a clue (see below).
No other communication is allowed.
Your final score is the total of the top cards on the five piles:
{| class="wikitable" style="width:auto; text-align:center;" border="2"
|+Final Score Ratings
!Points
!Overall impression
|-
| 0-5
|horrible, booed by the crowd...
|-
| 6-10
|mediocre, just a spattering of applause.
|-
|11-15
| honourable, but will not be remembered for very long...
|-
|16-20
|excellent, crowd pleasing.
|-
| 21-24
|amazing, will be remembered for a very long time!
|-
|25
|legendary, everyone left speechless, stars in their eyes
|}
==Card distribution ==
*Each card has a colour and a number.
{| class="wikitable" style="width:auto;" border="2"
|+Normal difficulty (50 cards)
!Red (r)
|{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}{{card|=1|background=#324|colour=#d03|size=2}}
|{{card|=2|background=#324|colour=#d03|size=2}}{{card|=2|background=#324|colour=#d03|size=2}}
|{{card|=3|background=#324|colour=#d03|size=2}}{{card|=3|background=#324|colour=#d03|size=2}}
|{{card|=4|background=#324|colour=#d03|size=2}}{{card|=4|background=#324|colour=#d03|size=2}}
|{{card|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}{{card|=1|background=#324|colour=#fe5|size=2}}
|{{card|=2|background=#324|colour=#fe5|size=2}}{{card|=2|background=#324|colour=#fe5|size=2}}
|{{card|=3|background=#324|colour=#fe5|size=2}}{{card|=3|background=#324|colour=#fe5|size=2}}
|{{card|=4|background=#324|colour=#fe5|size=2}}{{card|=4|background=#324|colour=#fe5|size=2}}
|{{card|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}{{card|=1|background=#324|colour=#2a7|size=2}}
|{{card|=2|background=#324|colour=#2a7|size=2}}{{card|=2|background=#324|colour=#2a7|size=2}}
|{{card|=3|background=#324|colour=#2a7|size=2}}{{card|=3|background=#324|colour=#2a7|size=2}}
|{{card|=4|background=#324|colour=#2a7|size=2}}{{card|=4|background=#324|colour=#2a7|size=2}}
|{{card|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}{{card|=1|background=#324|colour=#0ae|size=2}}
|{{card|=2|background=#324|colour=#0ae|size=2}}{{card|=2|background=#324|colour=#0ae|size=2}}
|{{card|=3|background=#324|colour=#0ae|size=2}}{{card|=3|background=#324|colour=#0ae|size=2}}
|{{card|=4|background=#324|colour=#0ae|size=2}}{{card|=4|background=#324|colour=#0ae|size=2}}
|{{card|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}{{card|=1|background=#324|colour=#fff|size=2}}
|{{card|=2|background=#324|colour=#fff|size=2}}{{card|=2|background=#324|colour=#fff|size=2}}
|{{card|=3|background=#324|colour=#fff|size=2}}{{card|=3|background=#324|colour=#fff|size=2}}
|{{card|=4|background=#324|colour=#fff|size=2}}{{card|=4|background=#324|colour=#fff|size=2}}
|{{card|=5|background=#324|colour=#fff|size=2}}
|}
===Multicolour cards===
*There are three variants that add a 6th colour: the multicolour.
*There are three difficulties:
====Tricky ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Tricky difficulty (+10 cards)
!Multicolour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Hard ====
*These cards get marked by a separate '''multicolour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+Hard difficulty (+5 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====Very Difficult ====
*These cards get marked by '''any colour clue'''.
{| class="wikitable" style="width:auto;" border="2"
|+ Avalanche difficulty (+10 cards)
!Multi-colour (m)
|{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{card|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
==Setup==
*8 clue tokens.
{| class="wikitable" style="width:auto;" border="2"
|+# cards dealt to each player
!# Players
!2
!3
!4
!5
|-
!# Cards (official rules)
|5
|5
|4
|4
|-
!# Cards (unofficial rules)
|6
|5
|4
|3
|}
==Game play==
Players take turns to either:
• Give a '''clue'''<br />
• '''Play''' a card, or<br />
• '''Discard''' a card
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
0ff6d210d28519eb2caa5c1fff1d1ac5318d012b
1542
1541
2023-11-18T05:49:04Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!Red (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!Multicolour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!Multi-colour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 단서 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
0f81f4c6f736136e89655114fc245175879668ce
1543
1542
2023-11-18T05:55:31Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!Red (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!Multicolour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!Multi-colour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 단서 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
===Clue===
* Possible when there is at least one clue token available.
*Clues indicate '''all''' cards of a certain colour, or '''all''' cards of a certain number.
you may indicate '''no''' cards of a color or number on BGA (you have no 5s, or you have no reds)
you may not indicate only a single card of the matching criteria if there is more than one
To do this:
1. The active player selects a card in another player's hand.<br />
2. The active player selects a clue option.<br />
3. One clue token is moved from 'available' to 'used'.
===Play===
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Play selected card' button.<br />
:• If the played card fits in any of the sequences, it is placed in the appropriate colour stack on the table.<br />
:• If the played card does not fit, it is placed in the discard pile and the team gets a ''misfire'' token.<br />
3. A replacement card is drawn.
===Discard===
This is only possible when there are fewer than 8 clue tokens available.
1. The active player selects a card in their hand.<br />
2. The active player selects the 'Discard selected card' button.<br />
3. The discarded card is placed in the discard pile.<br />
4. One clue token is moved from 'used' to 'available'.<br />
5. A replacement card is drawn.
==Game end==
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
139150a60ecd87a0a95afed7384d13e235654680
1544
1543
2023-11-18T06:07:18Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!Red (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!Yellow (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!Green (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!Blue (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!White (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!Multicolour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!Multi-colour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우(흑색의 경우 5)
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우(흑색의 경우 1 작은 경우)
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
869e660d1bbb4feffa44c745b69c880972ffd2f2
1545
1544
2023-11-18T06:08:21Z
Nilzzzzy
7482
/* 초급 */
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!Multicolour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!Multi-colour (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우(흑색의 경우 5)
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우(흑색의 경우 1 작은 경우)
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
fe81fa70d26bddfb02726556e99d6cc26d459278
1546
1545
2023-11-18T06:08:59Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우(흑색의 경우 5)
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우(흑색의 경우 1 작은 경우)
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* The game can end in several ways:
*1. All cards have been drawn from the deck. After this happens, everybody gets 1 more turn. The game ends with the score at the last turn.
*2. Your team played all possible cards. In this case, the game ends immediately and you receive the maximum possible score.
*3. Your team made three mistakes that caused misfires. In this case, you lose the game and get negative ten (-10) points.
*4. Your team 'abandons' the game. Although discouraged, you receive zero (0) points.
==Options==
=== Black Powder ===
*Clues cannot be given for the colour black.
* Black cards must be played in reverse order, from 5 to 1.
{| class="wikitable" style="width:auto;" border="2"
|+Black Powder (+10 cards)
!Black Powder (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Cheating==
*Players can cheat at Hanabi by:
**1. Sharing information via the chat user interface.
**2. Deliberately abandoning games.
* This is why ranking has been disabled for this game.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
5f0494eb23dd8832bf8ebbbfc11a00252894679a
1547
1546
2023-11-18T06:15:58Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* 카드 놓기에 세번 실패하면 게임이 끝나며 패배로 기록됩니다.
== 추가 설정 ==
==== 흑색 화약 ====
검정색에 대한 힌트를 줄 수 없습니다.
흑색 카드는 다음의 경우에만 놓을 수 있습니다.
* 해당 카드가 5일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 작은 경우
{| class="wikitable" style="width:auto;" border="2"
|+흑색 화약(+10장)
!흑색 (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[Category:Card games]]
d4ccb14193ef722f51fef561ec170124da3a7d6d
1548
1547
2023-11-18T06:16:58Z
Nilzzzzy
7482
/* Examples */
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* 카드 놓기에 세번 실패하면 게임이 끝나며 패배로 기록됩니다.
== 추가 설정 ==
==== 흑색 화약 ====
검정색에 대한 힌트를 줄 수 없습니다.
흑색 카드는 다음의 경우에만 놓을 수 있습니다.
* 해당 카드가 5일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 작은 경우
{| class="wikitable" style="width:auto;" border="2"
|+흑색 화약(+10장)
!흑색 (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
==Lingo==
When you play with others, certain words are used to describe certain objects or situations. Here is a short list.
;Marked:A card that is highlighted by a clue.
;Unmarked:A card that is not clued.
;chop:The oldest, unmarked card. The card that you have no information on and will chop from your hand.
;draw:The newest, unmarked card. The card that you have no information on and was freshly drawn.
; To bomb:A play that causes the third misfire-token. Sometimes called '''explosion'''
;Unique:A card that has no copy (left) in the deck.
; Double discard:When consecutive players have the same card on chop. A special problem, since, to each of the consecutive players, a number to chop does not look like a unique save.
;Twin chop:2 consecutive players have the same card on chop. Same as Double discard
;Double save:When a player has two consecutive unique cards, requiring consecutive save clues.
;Strategy:A set of rules / guidelines / conventions on how to interpret actions by players (including spending of clue-tokens).
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[분류:카드 게임]]
a10361512acabaecf090debc990c5cc635daf90b
1549
1548
2023-11-18T06:18:29Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* 카드 놓기에 세번 실패하면 게임이 끝나며 패배로 기록됩니다.
== 추가 설정 ==
==== 흑색 화약 ====
검정색에 대한 힌트를 줄 수 없습니다.
흑색 카드는 다음의 경우에만 놓을 수 있습니다.
* 해당 카드가 5일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 작은 경우
{| class="wikitable" style="width:auto;" border="2"
|+흑색 화약(+10장)
!흑색 (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
===Five Flamboyants===
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[분류:카드 게임]]
14651e118de036d556be5eb3089920eb0b0040d7
1550
1549
2023-11-18T06:20:00Z
Nilzzzzy
7482
/* Five Flamboyants */
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* 카드 놓기에 세번 실패하면 게임이 끝나며 패배로 기록됩니다.
== 추가 설정 ==
==== 흑색 화약 ====
검정색에 대한 힌트를 줄 수 없습니다.
흑색 카드는 다음의 경우에만 놓을 수 있습니다.
* 해당 카드가 5일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 작은 경우
{| class="wikitable" style="width:auto;" border="2"
|+흑색 화약(+10장)
!흑색 (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
==== 화려한 폭죽 5장 ====
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[분류:카드 게임]]
2fab1a4f79e4230f90fc0591bdf7f529ead68505
1551
1550
2023-11-18T06:26:38Z
Nilzzzzy
7482
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* 카드 놓기에 세번 실패하면 게임이 끝나며 패배로 기록됩니다.
== 추가 설정 ==
==== 흑색 화약 ====
검정색에 대한 힌트를 줄 수 없습니다.
흑색 카드는 다음의 경우에만 놓을 수 있습니다.
* 해당 카드가 5일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 작은 경우
{| class="wikitable" style="width:auto;" border="2"
|+흑색 화약(+10장)
!흑색 (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
==== 화려한 폭죽 5장 ====
After playing the last card of a colour, randomly select one of the following bonuses for immediate use:
*Gain a clue token.
*Gain a clue token and recover a life.
*Give a clue regarding a colour.
*Give a clue regarding a number.
* Shuffle a discarded card into the deck.
*Play a discarded card, if possible.
== 점수 ==
보드에 놓아진 카드 갯수가 점수입니다.
{|class="wikitable" style="width:auto; text-align:center;" border="2"
|+점수 평가
!점수
!Overall impression
|-
|0-5
|형편 없음. 관람객들의 야유가 쏟아집니다...
|-
|6-10
|인상적이지 않음. 영혼 없는 박수 정도나 나올까?
|-
|11-15
|인상적이긴 하지만 그리 기억될 만큼은 아닙니다...
|-
|16-20
|훌륭하며 관람객들도 만족한 듯 합니다.
|-
|21-24
|놀랍군요. 관람객들이 오랫동안 기억할 듯 합니다.
|-
|25-29
|이제 당신은 전설! 이 이상의 불꽃놀이는 없을 듯 합니다.
|-
|30
|신화적입니다! 불꽃놀이가 하늘의 별들보다도 찬란하게 빛납니다!
|}
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[분류:카드 게임]]
50c481f671512c2ed5c63b0151da11d0de296080
틀:Card
10
266
1523
2023-11-18T05:20:05Z
Nilzzzzy
7482
새 문서: <span style="background:{{{background|#fafafa}}};box-shadow:0.05rem 0.05rem 0.1rem 0.1rem rgba(0,0,0,0.2),inset 0 0 0 {{{borderThickness|0.1}}}rem {{{borderColour|#fff0}}};border-radius:0.2rem;padding-top:0.25rem;padding-bottom:0.25rem;padding-left:0.15rem;padding-right:0.15rem;line-height:calc({{{size|1}}}rem + 0.7rem);color:{{{colour|#000}}};text-shadow:0 0 calc({{{size|1}}}rem / 20) {{{outlineColour|#fff0}}},0 0 calc({{{size|1}}}rem / 20) {{{outlineColour|#fff0}}},0 0 calc({{...
wikitext
text/x-wiki
<span style="background:{{{background|#fafafa}}};box-shadow:0.05rem 0.05rem 0.1rem 0.1rem rgba(0,0,0,0.2),inset 0 0 0 {{{borderThickness|0.1}}}rem {{{borderColour|#fff0}}};border-radius:0.2rem;padding-top:0.25rem;padding-bottom:0.25rem;padding-left:0.15rem;padding-right:0.15rem;line-height:calc({{{size|1}}}rem + 0.7rem);color:{{{colour|#000}}};text-shadow:0 0 calc({{{size|1}}}rem / 20) {{{outlineColour|#fff0}}},0 0 calc({{{size|1}}}rem / 20) {{{outlineColour|#fff0}}},0 0 calc({{{size|1}}}rem / 20) {{{outlineColour|#fff0}}},0 0 calc({{{size|1}}}rem / 20) {{{outlineColour|#fff0}}},0 0 calc({{{size|1}}}rem / 20) {{{outlineColour|#fff0}}},0 0 calc({{{size|1}}}rem / 20) {{{outlineColour|#fff0}}};font-size:{{{size|1}}}rem;white-space: nowrap">{{{| }}}</span><noinclude>
{|class="wikitable" style="text-align:center;"
|+Playing card template examples for a BGA wiki page
!Type
|<code><nowiki>{{club}}</nowiki></code>
|<code><nowiki>{{spade}}</nowiki></code>
|<code><nowiki>{{heart}}</nowiki></code>
|<code><nowiki>{{diamond}}</nowiki></code>
|<code><nowiki>{{cardBack}}</nowiki></code>
|<code><nowiki>{{card|=A}}</nowiki></code>
|<code><nowiki>{{club|=A}}</nowiki></code>
|<code><nowiki>{{club|=A|colour=green}}</nowiki></code>
|-
!Result
|{{club}}
|{{spade}}
|{{heart}}
|{{diamond}}
|{{cardBack}}
|{{card|=A}}
|{{club|=A}}
|{{club|=A|colour=green}}
|}
'''Note:''' Game Help pages (e.g. '[[Gamehelpmachiavelli|GameHelpMachiavelli]]') display on Rules Summary pages
e.g. https://boardgamearena.com/gamepanel?game=machiavelli under HOW TO PLAY? > See More > RULES SUMMARY
{|class="wikitable" style="text-align:left;"
|+Available parameters
!Parameter
!Default value
!Example
!Result
!Description
|-
|<code style="color:#b00;">null</code>
|<code><nowiki>&nbsp;&nbsp;&nbsp;</nowiki></code>
|<code><nowiki>{{card|=A}}</nowiki></code>
|style="text-align:center;"|{{card|=A}}
|<b><i>Optional:</i></b> specify a card value e.g. <code>A</code> for Ace.
|-
|<code>size</code>
|<code>1</code>
|<code><nowiki>{{card|=A|size=1.5}}</nowiki></code>
|style="text-align:center;"|{{card|=A|size=1.5}}
|<b><i>Optional:</i></b> specify the text size in rem units.
|-
|<code>colour</code>
|<code>#000</code> (black)
|<code><nowiki>{{card|=A|colour=green}}</nowiki></code>
|style="text-align:center;"|{{card|=A|colour=green}}
|<b><i>Optional:</i></b> specify the text colour as a [https://developer.mozilla.org/en-US/docs/Web/CSS/color CSS colour].
|-
|<code>outlineColour</code>
|<code>#fff0</code> (transparent white)
|<code><nowiki>{{card|=A|colour=white|outlineColour=green}}</nowiki></code>
|style="text-align:center;"|{{card|=A|colour=white|outlineColour=green}}
|<b><i>Optional:</i></b> specify the text outline colour as a [https://developer.mozilla.org/en-US/docs/Web/CSS/color CSS colour].
|-
|<code>background</code>
|<code>#fafafa</code> (almost white)
|<code><nowiki>{{card|=A|colour=white|background=green}}</nowiki></code>
|style="text-align:center;"|{{card|=A|colour=white|background=green}}
|<b><i>Optional:</i></b> specify the background colour as a [https://developer.mozilla.org/en-US/docs/Web/CSS/color CSS colour].
|-
|<code>borderColour</code>
|<code>#fff0</code> (transparent white)
|<code><nowiki>{{card|borderColour=green}}</nowiki></code>
|style="text-align:center;"|{{card|borderColour=green}}
|<b><i>Optional:</i></b> specify the border colour as a [https://developer.mozilla.org/en-US/docs/Web/CSS/color CSS colour].
|-
|<code>borderThickness</code>
|<code>0.1</code>
|<code><nowiki>{{card|borderColour=green|borderThickness=0.2}}</nowiki></code>
|style="text-align:center;"|{{card|borderColour=green|borderThickness=0.2}}
|<b><i>Optional:</i></b> specify the border thickness in rem units.
|}
== Examples ==
=== Machiavelli ===
* The table has the set {{spade|=5}}{{diamond|=5|colour=blue}}{{heart|=5}} .
* A player may play a combination, such as {{spade|=6}}{{diamond|=6|colour=blue}}{{heart|=6}} or {{spade|=6}}{{spade|=7}}{{spade|=8}}, or may extend the existing set by playing {{club|=5|colour=green}} .
<pre>
* The table has the set {{spade|=5}}{{diamond|=5|colour=blue}}{{heart|=5}} .
* A player may play a combination, such as {{spade|=6}}{{diamond|=6|colour=blue}}{{heart|=6}} or {{spade|=6}}{{spade|=7}}{{spade|=8}}, or may extend the existing set by playing {{club|=5|colour=green}} .
</pre>
=== Palace ===
{|class="wikitable" style="width:auto; text-align:center;"
|+style="text-align:left;"|''The deck is already empty''
!Player
!In hand
!On table
!Stack top card
!style="text-align:left;"|Action
|-
|'''A'''
|{{heart|=3}}{{club|=3}}
{{spade|=4}}{{club|=4}}
|{{club|=7}}{{Diamond|=7}}{{spade|=7}}
{{cardBack}}{{cardBack}}{{cardBack}}
|{{diamond|=2}}
|style="text-align:left;"|Plays {{heart|=3}}{{club|=3}} .
|-
|'''B'''
| -
|{{Diamond|=8}}{{club|=J}}{{Diamond|=Q}}
{{cardBack}}{{cardBack}}{{cardBack}}
|{{heart|=3}}
|style="text-align:left;"|Plays {{Diamond|=8}} from the table.
|}
<pre>
{|class="wikitable" style="width:auto; text-align:center;"
|+style="text-align:left;"|''The deck is already empty''
!Player
!In hand
!On table
!Stack top card
!style="text-align:left;"|Action
|-
|'''A'''
|{{heart|=3}}{{club|=3}}
{{spade|=4}}{{club|=4}}
|{{club|=7}}{{Diamond|=7}}{{spade|=7}}
{{cardBack}}{{cardBack}}{{cardBack}}
|{{diamond|=2}}
|style="text-align:left;"|Plays {{heart|=3}}{{club|=3}} .
|-
|'''B'''
| -
|{{Diamond|=8}}{{club|=J}}{{Diamond|=Q}}
{{cardBack}}{{cardBack}}{{cardBack}}
|{{heart|=3}}
|style="text-align:left;"|Plays {{Diamond|=8}} from the table.
|}
</pre>
=== Hanabi ===
{|class="wikitable" style="text-align:center;"
|+Playing card template examples for a BGA wiki page
!Type
|<code><nowiki>{{HCardr}}</nowiki></code>
|<code><nowiki>{{HCardy}}</nowiki></code>
|<code><nowiki>{{HCardg}}</nowiki></code>
|<code><nowiki>{{HCardb}}</nowiki></code>
|<code><nowiki>{{HCardw}}</nowiki></code>
|<code><nowiki>{{HCardm}}</nowiki></code>
|<code><nowiki>{{HCardk}}</nowiki></code>
|-
!Result
|{{HCardr}}
|{{HCardy}}
|{{HCardg}}
|{{HCardb}}
|{{HCardw}}
|{{HCardm}}
|{{HCardk}}
|}
{|class="wikitable" style="text-align:left;"
|+Available parameters
!Parameter
!Default value
!Example
!Result
!Description
|-
|<code style="color:#b00;">null</code>
|<code><nowiki>&nbsp;&nbsp;</nowiki></code>
|<code><nowiki>{{HCardr|=1}}</nowiki></code>
|style="text-align:center;"|{{HCardr|=1}}
|<b><i>Optional:</i></b> specify a card value e.g. <code>1</code>.
|-
|<code>size</code>
|<code>2</code>
|<code><nowiki>{{HCardr|=1|size=1.5}}</nowiki></code>
|style="text-align:center;"|{{HCardr|=1|size=1.5}}
|<b><i>Optional:</i></b> specify the text size in rem units.
|}
[[Category:Card templates]]
</noinclude>
dd85f9e0439eb9a6279c4c4a85dc2137b9e16b38
틀:HCardr
10
267
1524
2023-11-18T05:21:17Z
Nilzzzzy
7482
새 문서: {{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour={{r}}|background=#302141|colour={{r}}|size={{{size|2}}}}}
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour={{r}}|background=#302141|colour={{r}}|size={{{size|2}}}}}
0c9d44ac4f0918ea5ee1544c4f023ce9790399e2
1528
1524
2023-11-18T05:28:37Z
Nilzzzzy
7482
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.15}}}|borderColour=#ff0000|background=#302141|colour=#ff0000|size={{{size|2}}}}}
61dff4c131f670f9a1642cf67b420b9e74d1d9dc
틀:HCardy
10
268
1525
2023-11-18T05:22:08Z
Nilzzzzy
7482
새 문서: {{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour={{y}}|background=#302141|colour={{y}}|size={{{size|2}}}}}
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour={{y}}|background=#302141|colour={{y}}|size={{{size|2}}}}}
1c33d5edd1bc38f627494d45d87d92105643b217
1527
1525
2023-11-18T05:27:38Z
Nilzzzzy
7482
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.15}}}|borderColour=#ffd400|background=#302141|colour=#ffd400|size={{{size|2}}}}}
a176cd178cc38cc179576ce4607d78b0f753faf0
틀:HCardg
10
269
1531
2023-11-18T05:31:38Z
Nilzzzzy
7482
새 문서: {{card|={{{| }}}|borderThickness={{{border|0.15}}}|borderColour=#00ff00|background=#302141|colour=#00ff00|size={{{size|2}}}}}
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.15}}}|borderColour=#00ff00|background=#302141|colour=#00ff00|size={{{size|2}}}}}
690737479ddd5c3b3d8e5ef20401c7eb3504894e
틀:HCardb
10
270
1532
2023-11-18T05:32:19Z
Nilzzzzy
7482
새 문서: {{card|={{{| }}}|borderThickness={{{border|0.15}}}|borderColour=#0000ff|background=#302141|colour=#0000ff|size={{{size|2}}}}}
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.15}}}|borderColour=#0000ff|background=#302141|colour=#0000ff|size={{{size|2}}}}}
c39b7eafeba48ea022d5a64d43f77521d4949856
틀:HCardw
10
271
1533
2023-11-18T05:32:53Z
Nilzzzzy
7482
새 문서: {{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour=#000000|background=#302141|colour=#000000size={{{size|2}}}}}
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour=#000000|background=#302141|colour=#000000size={{{size|2}}}}}
c5eeae7a5656e782a857ac4bcf69ac6f61cac906
1535
1533
2023-11-18T05:34:38Z
Nilzzzzy
7482
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour=#ffffff|background=#302141|colour=#ffffff|size={{{size|2}}}}}
702c5ce2d62410976d844d8fa780572d07b30f63
1538
1535
2023-11-18T05:40:15Z
Nilzzzzy
7482
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.15}}}|borderColour=#ffffff|background=#302141|colour=#ffffff|size={{{size|2}}}}}
072d1d8bb2c872c3ee361715d801a8a2aae51f01
틀:HCardm
10
272
1536
2023-11-18T05:39:37Z
Nilzzzzy
7482
새 문서: {{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour=#83007D|background=#302141|colour=#C4B|size={{{size|2}}}}}
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.05}}}|borderColour=#83007D|background=#302141|colour=#C4B|size={{{size|2}}}}}
7b46be7d30580cdfeb3a5aa64e7e9aa3355ce653
1537
1536
2023-11-18T05:39:55Z
Nilzzzzy
7482
wikitext
text/x-wiki
{{card|={{{| }}}|borderThickness={{{border|0.15}}}|borderColour=#83007D|background=#302141|colour=#C4B|size={{{size|2}}}}}
d792e8861049fc3775f93d37e2e9ce68f8b98434
Gamehelphanabi
0
265
1552
1551
2023-11-18T06:28:50Z
Nilzzzzy
7482
/* 화려한 폭죽 5장 */
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* 카드 놓기에 세번 실패하면 게임이 끝나며 패배로 기록됩니다.
== 추가 설정 ==
==== 흑색 화약 ====
검정색에 대한 힌트를 줄 수 없습니다.
흑색 카드는 다음의 경우에만 놓을 수 있습니다.
* 해당 카드가 5일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 작은 경우
{| class="wikitable" style="width:auto;" border="2"
|+흑색 화약(+10장)
!흑색 (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
==== 화려한 폭죽 5장 ====
색상의 마지막 카드를 사용한 후 즉시 사용할 수 있도록 다음 보너스 중 하나를 무작위로 선택됩니다.
*단서 토큰을 얻습니다.
*단서 토큰을 얻고 생명을 회복하십시오.
*색상에 대한 힌트를 주세요.
*숫자에 대한 힌트를 주세요.
*버린 카드를 덱에 섞습니다.
*가능하면 버려진 카드를 사용하십시오.
== 점수 ==
보드에 놓아진 카드 갯수가 점수입니다.
{|class="wikitable" style="width:auto; text-align:center;" border="2"
|+점수 평가
!점수
!Overall impression
|-
|0-5
|형편 없음. 관람객들의 야유가 쏟아집니다...
|-
|6-10
|인상적이지 않음. 영혼 없는 박수 정도나 나올까?
|-
|11-15
|인상적이긴 하지만 그리 기억될 만큼은 아닙니다...
|-
|16-20
|훌륭하며 관람객들도 만족한 듯 합니다.
|-
|21-24
|놀랍군요. 관람객들이 오랫동안 기억할 듯 합니다.
|-
|25-29
|이제 당신은 전설! 이 이상의 불꽃놀이는 없을 듯 합니다.
|-
|30
|신화적입니다! 불꽃놀이가 하늘의 별들보다도 찬란하게 빛납니다!
|}
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[분류:카드 게임]]
fb8bac19ea3f7b482882f33b1ef30b9e96d1e490
1554
1552
2023-11-20T07:18:40Z
Nilzzzzy
7482
/* 점수 */
wikitext
text/x-wiki
==개요 ==
하나비는 협동하여 더 멋진 불꽃놀이를 완성하는 게임입니다.
== 구성 ==
==== 초급 ====
{| class="wikitable" style="width:auto;" border="2"
|+초급:5색(50장)
!빨강 (r)
|{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}{{HCardr|=1|background=#324|colour=#d03|size=2}}
|{{HCardr|=2|background=#324|colour=#d03|size=2}}{{HCardr|=2|background=#324|colour=#d03|size=2}}
|{{HCardr|=3|background=#324|colour=#d03|size=2}}{{HCardr|=3|background=#324|colour=#d03|size=2}}
|{{HCardr|=4|background=#324|colour=#d03|size=2}}{{HCardr|=4|background=#324|colour=#d03|size=2}}
|{{HCardr|=5|background=#324|colour=#d03|size=2}}
|-
!노랑 (y)
|{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}{{HCardy|=1|background=#324|colour=#fe5|size=2}}
|{{HCardy|=2|background=#324|colour=#fe5|size=2}}{{HCardy|=2|background=#324|colour=#fe5|size=2}}
|{{HCardy|=3|background=#324|colour=#fe5|size=2}}{{HCardy|=3|background=#324|colour=#fe5|size=2}}
|{{HCardy|=4|background=#324|colour=#fe5|size=2}}{{HCardy|=4|background=#324|colour=#fe5|size=2}}
|{{HCardy|=5|background=#324|colour=#fe5|size=2}}
|-
!초록 (g)
|{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}{{HCardg|=1|background=#324|colour=#2a7|size=2}}
|{{HCardg|=2|background=#324|colour=#2a7|size=2}}{{HCardg|=2|background=#324|colour=#2a7|size=2}}
|{{HCardg|=3|background=#324|colour=#2a7|size=2}}{{HCardg|=3|background=#324|colour=#2a7|size=2}}
|{{HCardg|=4|background=#324|colour=#2a7|size=2}}{{HCardg|=4|background=#324|colour=#2a7|size=2}}
|{{HCardg|=5|background=#324|colour=#2a7|size=2}}
|-
!파랑 (b)
|{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}{{HCardb|=1|background=#324|colour=#0ae|size=2}}
|{{HCardb|=2|background=#324|colour=#0ae|size=2}}{{HCardb|=2|background=#324|colour=#0ae|size=2}}
|{{HCardb|=3|background=#324|colour=#0ae|size=2}}{{HCardb|=3|background=#324|colour=#0ae|size=2}}
|{{HCardb|=4|background=#324|colour=#0ae|size=2}}{{HCardb|=4|background=#324|colour=#0ae|size=2}}
|{{HCardb|=5|background=#324|colour=#0ae|size=2}}
|-
!하양 (w)
|{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}{{HCardw|=1|background=#324|colour=#fff|size=2}}
|{{HCardw|=2|background=#324|colour=#fff|size=2}}{{HCardw|=2|background=#324|colour=#fff|size=2}}
|{{HCardw|=3|background=#324|colour=#fff|size=2}}{{HCardw|=3|background=#324|colour=#fff|size=2}}
|{{HCardw|=4|background=#324|colour=#fff|size=2}}{{HCardw|=4|background=#324|colour=#fff|size=2}}
|{{HCardw|=5|background=#324|colour=#fff|size=2}}
|}
==== 중급 이상 ====
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+10장), 색의 향연:다색(+10장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
====== 변형 ======
{| class="wikitable" style="width:auto;" border="2"
|+중급:6색(+5장)
!다색 (m)
|{{HCardm|=1|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=2|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=3|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=4|background=#324|colour=#717|outlineColour=#fff|size=2}}
|{{HCardm|=5|background=#324|colour=#717|outlineColour=#fff|size=2}}
|}
== 진행 ==
게임이 시작되면 모든 플레이어들은 4장의 카드를 받습니다. 자신 외의 모든 플레이어의 카드를 볼 수 있습니다. 모든 플레이어는 아래의 세가지 행동으로 소통해야됩니다. 채팅 등 이외의 수단은 사용하는 것은 권장되지 않습니다.
==== 힌트 주기 ====
게임이 시작되면 게임 보드 위에 힌트 토큰이 8개가 있을 겁니다. 다른 플레이어에게 힌트를 주기 위해서는 토큰을 사용해야합니다.
줄 수 있는 힌트는 다음과 같습니다.
* 어떤 종류의 숫자 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 3장의 1 카드를 알려줍니다.</sup>
* 어떤 종류의 색 카드가 있는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 있는 노랑 카드를 알려줍니다.</sup>
* 어떤 종류의 숫자 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 1 카드가 없음을 알려줍니다.</sup>
* 어떤 종류의 색 카드가 없는지 알려줄 수 있습니다. <sup>예) 플레이어 1님의 손에 노랑 카드가 없음을 알려줍니다.</sup>
==== 카드 놓기 ====
카드를 한 장 사용할 수 있습니다. 다음의 경우에 보드 위에 놓을 수 있습니다.
* 해당 카드가 1일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 큰 경우
이외의 경우에는 실패하게 되며 카드는 버려집니다.
그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
==== 카드 버리기 ====
힌트 토큰이 7개 이하일 경우 카드를 버리고 힌트 토큰을 하나 가져옵니다. 그 후, 덱에 카드가 남아있다면 카드 한 장을 가져옵니다.
== 종료 ==
* 덱이 비워지면 모든 플레이어는 마지막 턴을 진행한 후 게임이 끝납니다.
* 놓을 수 있는 카드가 모두 놓아졌다면 게임이 끝납니다.
* 카드 놓기에 세번 실패하면 게임이 끝나며 패배로 기록됩니다.
== 추가 설정 ==
==== 흑색 화약 ====
검정색에 대한 힌트를 줄 수 없습니다.
흑색 카드는 다음의 경우에만 놓을 수 있습니다.
* 해당 카드가 5일 경우
* 이미 보드에 놓아진 같은 종류의 색 카드 보다 숫자가 1 작은 경우
{| class="wikitable" style="width:auto;" border="2"
|+흑색 화약(+10장)
!흑색 (k)
|{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=5|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=4|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=3|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}{{card|=2|background=#324|colour=#000|outlineColour=#fff|size=2}}
|{{card|=1|background=#324|colour=#000|outlineColour=#fff|size=2}}
|}
==== 화려한 폭죽 5장 ====
색상의 마지막 카드를 사용한 후 즉시 사용할 수 있도록 다음 보너스 중 하나를 무작위로 선택됩니다.
*단서 토큰을 얻습니다.
*단서 토큰을 얻고 생명을 회복하십시오.
*색상에 대한 힌트를 주세요.
*숫자에 대한 힌트를 주세요.
*버린 카드를 덱에 섞습니다.
*가능하면 버려진 카드를 사용하십시오.
== 점수 ==
보드에 놓아진 카드 갯수가 점수입니다.
{|class="wikitable" style="width:auto; text-align:center;" border="2"
|+점수 평가
!점수
!관람객 평가
|-
|0-5
|형편 없음. 관람객들의 야유가 쏟아집니다...
|-
|6-10
|인상적이지 않음. 영혼 없는 박수 정도나 나올까?
|-
|11-15
|인상적이긴 하지만 그리 기억될 만큼은 아닙니다...
|-
|16-20
|훌륭하며 관람객들도 만족한 듯 합니다.
|-
|21-24
|놀랍군요. 관람객들이 오랫동안 기억할 듯 합니다.
|-
|25-29
|이제 당신은 전설! 이 이상의 불꽃놀이는 없을 듯 합니다.
|-
|30
|신화적입니다! 불꽃놀이가 하늘의 별들보다도 찬란하게 빛납니다!
|}
== ELO rating==
*If you are playing with ELO rating on, your ELO may be changed at the end of the game.
*Here is how it works:
*1. Every player on the team is temporarily considered as having the average ELO rating of the team.
*2. The system will generate a bot associated with the score your team has achieved (let’s call it '''''Hanabot''''').
**• Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolour), the number of players on the team and, most importantly, your team's score.
**• All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players.
*3. Your team (actually your team's average ELO) will now compete against Hanabot.
**• The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot.
** • If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000.
*You can find <b>[http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 all bots' ELO ratings here]</b>
* The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. (This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills.)
*If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points.
*To be confirmed: I think the ELO-system has had an overhaul.
==Conventions==
* If you want to play "full information" style, meaning that you wait until you know both the colour and number of a card before you play it, you will likely be short on clue tokens in >99% of the decks.
*The logical conclusion is that you cannot play a full information style game and the team must agree on some sort of meta-information. The meta-information is coded in a convention.
*Many players have different kinds of conventions.
**''Note: not all conventions are added to the BGA list. Please respect the convention the table creator wants to play.''
*When different players in the same team assign different meta-information to the same clue, the game becomes unplayable.
**This is why there is an option to display the convention for the table.
**See '''[https://boardgamearena.com/forum/viewtopic.php?t=26863 this forum post]''' started by '''[https://boardgamearena.com/player?id=84207926 user Romain672]'''.
*Ideally, all players adhere to the convention, to avoid miscommunication.
*Below, the meta-information of several conventions is explained.
===Standard===
*Players assume the following meta-information:
**Every marked card will be playable at some point.
==== Number clue====
*Cards with a number-clue on them must be saved to be played later on in the game
*Saved cards can be safely played when all "number-1" cards are played.
**''Saved cards are played from oldest to newest.''
==== Colour clue ====
*The newest, previously unmarked card, is the next playable card in the sequence.
*The oldest, unmarked card is safe to discard.
**If a player has a card that they are sure they will never be able to play, e.g. cards marked by a blue clue when the blue stack is already complete, these card must be discarded in priority.
==== Bad clues ====
* A clue that marks 0 new cards.
* A clue that tells a ''lie'' (i.e. does not conform to the meta-information above).
*A clue that marks unplayable or duplicate cards, unless it saves a card at the chop position that does not have another copy of the card in the deck or other players' hands.
**e.g. Marking 4s in another hand if your hand could have a copy of that 4.
*Sometimes, a "bad" clue cannot be avoided.
**''e.g. Save a unique 3 using a number clue which also marks unplayable cards.''
**''e.g. A colour clue from a flamboyant must be used and it is used to mark 0 new cards.''
*When a ''lie'' has been told, it needs to be corrected.
*A correction clue can never mean "play", it can only mean "discard".
{{infoBoxes3 |maxWidth=625
|title1=Standard convention example 1
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|card1=2|card1Colour=red
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It's Amy's turn, and Bob knows his chop card is {{card|=5}}.
* Amy will give a red {{card|background=red}} clue to Bob.
* This will tell Bob that the newest card is the next playable in the sequence (so must be {{card|=2|background=#324|colour=red|size=1.5}}), and that the other red can be {{card|=3|background=#324|colour=red|size=1.5}}, {{card|=4|background=#324|colour=red|size=1.5}}, or {{card|=5|background=#324|colour=red|size=1.5}} (because it must be playable at some later point in the game).
|title2=Standard convention example 2
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=2|card1Colour=red
|card2=5|card2Colour=yellow
|card3=1|card3Colour=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue5=5|clue5Colour=lightgrey
|clue3Colour=red
|card1=5|card1Colour=white
|card2=4|card2Colour=yellow
|card3=3|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=2|card1Colour=white
|card2=4|card2Colour=lightgreen
|card3=1|card3Colour=yellow
|card4=4|card4Colour=red
|card5=3|card5Colour=yellow
}}
</div>
* It is Amy's turn again, and Bob knows his oldest card is {{card|=5}}, and his middle card is {{card|background=red}}.
* Amy will give a red {{card|background=red}} clue to Cat.
* This will tell Cat that her marked card is the next playable in the sequence (so must be {{card|=4|background=#324|colour=red|size=1.5}}, because {{card|=3|background=#324|colour=red|size=1.5}} is already marked).
* This will give Bob the meta-information that his saved red card, is {{card|=3|background=#324|colour=red|size=1.5}}.
** ''This particular move is sometimes called prompting, and is a common way to allow a card that is saved by colour to get played without re-cluing it.''
|title3=Standard convention example 3
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=|cardBackground=#324
|card1=1|card1Colour=red
|card2=5|card2Colour=yellow
|card3Background=lightgreen
|card4=3|card4Colour=deepskyblue
|card5=4|card5Colour=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3=2|clue3Colour=lightgrey
|card1=3|card1Colour=red
|card2=4|card2Colour=yellow
|card3=2|card3Colour=red
|card4=3|card4Colour=deepskyblue
|card5=5|card5Colour=lightgreen
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=4|card1Colour=lightgreen
|card2=1|card2Colour=yellow
|card3=4|card3Colour=red
|card4=3|card4Colour=yellow
|card5=2|card5Colour=yellow
}}
</div>
* It is Amy's turn, and Bob knows his middle card is {{card|=2}}.
* Amy will give a red {{card|background=#d03}} clue to Bob.
* This will tell Bob that his newest card is the next playable in the sequence (so must be {{card|=3|background=#324|colour=#d03|size=1.5}}, because {{card|=2|background=#324|colour=#d03|size=1.5}} is now visible with 100% information).
}}
===Finesse===
*Finesse builds on the standard convention (making it a bit more complex).
*In the finesse convention, the timing of the clue gives you extra information.
*You can assume the following meta-information:
**Every card that gets marked, will be playable at some point.
**If the oldest, unmarked card gets marked with a number-clue, then the clue meant "save this/these card(s)". (It is custom to play saved cards from oldest to newest when appropriate.)
** A clue that doesn't mark the oldest card, means that the newest, previously unmarked card, is the next playable card in the sequence.
**The oldest, unmarked card is safe to discard unless that player is busy by having a "known" play or discard.
***''Obviously, if a player has a card that they are sure they will never be able to play, for example a card on which is marked as 1 when all the 1s have already been played, should be discarded in priority.''
**Clues are given by the last possible player.
***When the timing of a clue doesn't match your expectations, you can draw certain conclusions (see next section: special interpretations)
====Special interpretations====
*When receiving a clue for the "next playable card in the sequence", the linking cards are not limited to already marked cards (like in standard convention).
*The newest, unmarked cards in every player's hand should be considered as well.
{{infoBoxes3 |maxWidth=625
|title1=Example of finesse
|body1=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
|title2=Example of reversed finesse
|body2=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
{{cardholder|player=Cat|cardBackground=#324
|card1=1|card1Colour=deepskyblue
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Bob.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence.
* Bob sees that the newest, unmarked card in Cat's hand is of the same colour (blue) '''and''' playable now. Bob concludes it is a finesse, with the players in reversed order, so his blue card must be {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
|title3=Example of a bluff
|body3=<div style="display:flex;flex-flow:row wrap;gap:1rem;">
{{cardholder|player=Table|arrow=
|card1Background=red
|card2Background=yellow
|card3Background=lightgreen
|card4Background=deepskyblue
|card5Background=white
}}
{{cardholder|player=Amy|cardBackground=#bbb}}
{{cardholder|player=Bob|cardBackground=#324
|card1=1|card1Colour=white
|card2=5|card2Colour=yellow
|card3=3|card3Colour=deepskyblue
|card4=1|card4Colour=white
|card5=2|card5Colour=white
}}
{{cardholder|player=Cat|cardBackground=#324
|clue3Colour=deepskyblue
|card1=5|card1Colour=red
|card2=2|card2Colour=red
|card3=2|card3Colour=deepskyblue
|card4=2|card4Colour=lightgreen
|card5=2|card5Colour=yellow
}}
</div>
* Amy gives a blue {{card|background=deepskyblue}} clue to Cat.
* This gives the information that {{card|=2|background=#324|colour=deepskyblue|size=1.5}} is the next playable card in the sequence, and that Bob is either not allowed to give a blue {{card|background=deepskyblue}} clue, or has something to play.
* Since Bob has no marked cards, he was not blocked from giving a blue {{card|background=deepskyblue}} clue, so he must have something to play.
* This something, must be the missing link ({{card|=1|background=#324|colour=deepskyblue|size=1.5}}, to enable {{card|=2|background=#324|colour=deepskyblue|size=1.5}}) that makes {{card|=2|background=#324|colour=deepskyblue|size=1.5}} the next playable card.
* Since there is no logical (marked) card that could be {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, Bob must assume his newest, unmarked card is {{card|=1|background=#324|colour=deepskyblue|size=1.5}} and blind-plays this card.
* However, at this point the "lie" is revealed (because the colour of the played card does '''not''' match the colour of the finesse-clue).
* The blind-played card is '''not''' {{card|=1|background=#324|colour=deepskyblue|size=1.5}}, but {{card|=1|background=#324|colour=white|size=1.5}}. Cat, up to this point, was thinking she had {{card|=1|background=#324|colour=deepskyblue|size=1.5}}.
* Bob's blind-play gives Cat extra information: her blue card is in fact {{card|=2|background=#324|colour=deepskyblue|size=1.5}}.
}}
*If a marked card gets discarded it means:
**The copy of that card is already marked in someone else's hand, and the discarding player is the first to realize this; or
**The copy of that card MUST be marked in a future clue (because a save-clue will be given that will mark the copy card as collateral).
====Clues you should avoid giving (bad clues)====
*As a special remark: don't mark useless, or duplicate cards. So if you have a saved 4, you are forbidden from marking 4s, unless you are sure you are not holding a copy of that
==== Meaning of skipping a player / stealing clues in Finesse convention====
* There are different approaches among finesse-convention-players about who should clue whom. So this section will be devided into sub-sections. The order does not say anything about which approach is more common on BGA. There are a lot of players following each idea.
*If you allow for skipping (without assigning information to it), a lot of potential information is destroyed. Note that this section is getting re-edited over and over. So don't modify it, or keep it neutral.
*With bga's conventions, the first approach is easier and more instinctif. But the second approach will give better long term results. And of course it is important for success, that in a game, the group of players follows the same idea. If they get mixed, it will most likely result in bombs. If that happens, it does not mean, the other player is "bad" - it merely means, they follow a different idea. So you can only try to find a common ground for the next game or play with another group next time.
=====a) Skipping / stealing should be avoided=====
To summarize what we already know about finesse convention:
1. Ever marked card will be playable at some point.
2. A number-clue that marks the CHOP card is a "save this for later"-clue.
3. Every other clue means: the newest, previously unmarked card, is the next playable card.
4. If you have no known playable card (or known safe-to-discard card), your CHOP card is safe to discard.
5. A clue is given by the last possible player.
*If more than 1 person are able to give the same clue, then the last possible person should give that clue.
*In finesse convention skipping (Alice clues Cat, instead of Bob; then Bob is skipped) means either:
**1. The Bob is forbidden from giving that clue; or
**2. The Bob has something to play.
*The main problem with this interpretation, is that "discard management" destroys the assumption that your CHOP is safe to discard.
*When applying this style of finesse convention, you assume that players use a bad strategy (see section [[Gamehelphanabi#Strategy|Strategy]]) of not-saving-valuable cards.
=====b) Skipping / stealing is for discard-management=====
This style is one way of applying finesse convention. You chop might still be that said card is a nice-to-have like a NON-unique 2 or 3 that is not yet playable. Without knowing your chop card, it is good to handle each-other's chop situation by preferably letting players with definitely useless chop-cards discard rather than discarding your own unknown card. Skipping/stealing is a term that is often used for a situation, where giving a clue is not left for the last possible player to do. ''e.g. Alice saves a card on chop of Cat, potentially leaving Bob without a known play or a useful/necessary clue to give.''
When getting skipped without having a play or useful option to clue, it most likely means that your chop card is not very useful.
These are valid reasons for skipping you:
*Your chop-card is trash (a copy of the card is already played/marked)
*Your chop-card is redundant: Another copy of it is on another player's (or your own) hand as well, so discarding it is no loss (or it has low priority like a high number when it's very early in the game).
*You might still have something nice on chop, but the player sitting before already received information that their chop might be something very good (from earlier discard-behaviour like NOT being skipped over by the player sitting before them on earlier turns) and they are reluctant to discard for that reason.
* The clue given is a play-clue for a card that might be in your hand so you couldn't know whether you want the other card or not. The player skipping you knows that you want it and therefore takes away the decision.
This approach sacrifices some saving-clue-tokens option (that might be achieved on a stricter dogma about who should clue whom) in order to be able to keep nice cards in the game for longer and discard useless cards instead and by that often get those cards played before they would be discarded.
*This convention is better for players who play efficient enough to rarely struggle with clue-shortness and can therefore afford being more careful about not losing first copies.
*If a group often struggles with clue-shortness then skipping-dogma (as proposed by other conventions) might as well improve their overall results. If the problem for not achieving 30 points usually isn't clue-shortness but getting bottom-decked (or heavily delayed from losing earlier a card that could be played now), then results can get better with this discard-management convention.
Planning ahead is a vital aspect of the game. By carefully deciding on who to let clue and whom to skip, it is often possible to
*avoid twin-chops before they become an issue
*avoid not having enough clue tokens to save all necessary cards
* get the discard you were waiting for (when a player has 2 copies of the same playable card and you want them to discard before clueing it)
===Others conventions===
*For others conventions, see '''[https://docs.google.com/document/d/1VzgN6WoeYwh5NYtHECzUNZqFvpVcg-EdObU-YNMlyhc/edit this google document]'''
==Strategy==
*In addition to the convention(s), there is also some strategy to the game.
*You should '''not''' confuse strategy with convention! Strategy is '''team''' vs '''deck'''; convention is communication within the team.
* A simple example of strategy is saving 2s in 2-player games.
** Using number-2-clue to communicate that those cards need to be saved, is a convention.
===Examples===
*More advanced players will try to avoid losing as many "first" (non-unique) cards as possible.
*It's a good strategy to keep good cards in the game as long as possible - even if they are not yet playable.
** ''The other copy of that card might be far down the draw pile.''
*Trying to mark at least 12 cards with the first 8 clue-tokens.
**This gives 99% chance of always having enough tokens in the game.
*Not using the last two clue-tokens for "single plays".
** This avoids running out of clue-tokens in times when you need to save critical cards.
[[분류:카드 게임]]
b4b785d553045005c4edc2d50e6c98b7ef4b3445
Gamehelpthirtyone
0
264
1553
1520
2023-11-18T18:38:14Z
Nilzzzzy
7482
/* 점수 */
wikitext
text/x-wiki
== 개요 ==
트럼프 카드를 사용하는 클래식 카드 게임이다.
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
3. 카드 더미에 카드가 부족할 경우 마지막 차례를 진행합니다.
== 점수 ==
누군가 31이나 불꽃을 완성하면 즉시 라운드가 종료됩니다.
동점일 경우 라운드 스톱을 선언한 사람이 점수가 더 높은 것으로 취급합니다. 그 외의 경우 무늬로 승패를 가립니다.(스다하클이 아닙니다. 현재 확인한 것은 클로버> 스페이드> 다이아, 하트> 다이아)
2명 이상이 트리플일 경우, 더 높은 등급이 더 높은 것으로 취급합니다.
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
트리플은 30.5점, 불꽃(A 트리플)은 32점으로 취급합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다.
여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
7c271d24379387c0ce3404d772df8ad854a65dd1
Gamehelptwelvechips
0
273
1555
2023-11-20T16:19:08Z
Doobooyooboo
9323
한글
wikitext
text/x-wiki
== '''개요''' ==
전체 칩의 값이 21을 초과하지 않도록 칩을 내려놓으며 모아보세요.
게임에서 사용되는 칩은 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 입니다.
4인 게임에서는 추가로 3 4 9 10을 추가하여 사용합니다.
== '''차례''' ==
자신의 차례에 칩을 선택해 내려놓으세요. (선택하는 칩은 이전 칩과 무관합니다.)
모든 플레이어가 내려놓았으면 가장 높은 수의 칩을 낸 플레이어(동점이라면 가장 높은 수의 칩을 먼저 낸 플레이어)는 이번에 내려놓은 칩들 중 하나를 먼저 골라서 가져가고,
시계 방향으로 모두가 남은 칩들 중 하나씩을 선택해 가져갑니다.
가져간 칩은 다음 두 가지 규칙을 따릅니다.
1) 가장 먼저 가져간 플레이어(다시 말해, 가장 먼저 가장 높은 수의 칩을 낸 플레이어)는 자신의 앞에 가져온 칩을 내려놓고 나머지 플레이어들은 자신의 손으로 가져갑니다.
2) 빨간색 칩은 다른 색 칩보다 우선적으로 가져가야 합니다.
그 후 먼저 가져간 플레이어는 이제부터 새로운 라운드의 시작 플레이어가 됩니다.
== '''라운드 종료''' ==
라운드를 시작해야 하는 플레이어의 손에 칩이 남아 있지 않다면(다시 말해 칩이 모두 플레이어 앞에 펼쳐졌다면) 라운드가 종료됩니다.
플레이어 손에 남은 칩은 전부 각자 앞에 펼쳐놓습니다.
칩의 합계가 21을 초과한 플레이어는 모두 이번 라운드에서 제외됩니다.
남은 플레이어 중 칩의 합계가 가장 높은 플레이어가 점수타일을 받습니다.
만약 모든 플레이어가 제외됐다면 그 중 칩의 합계가 가장 높은 플레이어가 점수타일을 받습니다.
위 두가지 상황에서 동점이라면 동점인 플레이어들은 모두 점수타일을 받습니다.
== '''게임 종료''' ==
점수 타일 3개를 먼저 모은 플레이어가 승리합니다.
동시에 3개가 됐다면 함께 승리합니다.
ee73e061742271b8ff38a82a09aba2544a108748
Gamehelppandemic
0
189
1556
1250
2023-11-25T11:48:54Z
2022JUN
9329
wikitext
text/x-wiki
팬데믹은 전 지구를 휩쓸고 있는 4개의 질병에 대항하는 영웅들의 이야기입니다!
1. 게임 종료 조건
- 승리 조건
* 4개의 질병에 대한 치료제를 개발할 경우
- 패배 조건
* 질병 토큰을 추가해야 할 때 해당 질병 토큰이 부족할 경우
* 카드를 뽑아야 할 때 뽑을 카드가 부족할 경우
* 확산 마커가 마지막 칸에 닿을 경우
2. 차례 진행 순서
- 원하는 순서대로 4개의 행동을 수행하기
- 카드 2장 뽑기
* 전염 카드가 나온다면 전염 카드의 내용을 즉시 수행
- 감염 단계에 따라 감염 카드를 뽑고 질병 토큰 추가
3. 행동
- 이동: 선으로 연결된 도시와 도시 사이를 이동
- 비행: 이동을 원하는 도시 카드를 사용하여 해당 도시로 이동
- 전용기 이용: 현재 도시와 같은 도시 카드를 사용하여 원하는 도시로 이동
- 정기 항공편 이용 : 연구소에서 다른 연구소로 이동
- 질병 치료: 현재 위치한 도시에 있는 질병 토큰 1개를 제거
- 정보 공유: 현재 위치한 도시에 있는 다른 플레이어와 현재 위치의 도시 카드를 주기/받기
- 연구소 건설: 현재 도시와 같은 도시 카드를 사용하여 현재 위치에 연구소 건설 (연구소가 부족하면 기존 연구소를 현재 위치로 이동)
- 치료제 개발: 연구소에서 같은 색상의 도시 카드 5장을 사용하여 해당 색상 질병의 치료제 개발
4. 치료제 개발 보너스
- 치료제가 개발되면 현재 위치에 있는 모든 해당 색상 질병을 한번의 행동으로 제거 가능
- 치료제가 개발된 질병 토큰이 보드에서 모두 제거되면 해당 질병은 근절이 되어 더 이상 추가되지 않음
5. 이벤트 카드
- 이벤트 카드 사용은 행동이 소모되지 않음
- 이벤트 카드는 본인의 차례가 아니어도 사용할 수 있음
6. 카드 소지 제한
- 카드는 언제나 7장까지만 가지고 있을 수 있음
- 8장을 넘게 갖게 되면 즉시 카드가 7장이 되게 버려야 함
- 이 때, 사용 가능한 이벤트 카드가 있다면 사용하여 손의 카드를 줄일 수 있음
7. 게임 팁
- 전염 카드가 나올 때마다 버려진 감염 카드가 감염 더미의 위로 다시 추가됩니다. 즉, 기존에 질병이 발병한 곳 위주로 질병이 추가되기 때문에 나왔던 도시를 파악하는 것이 중요합니다.
- 게임의 승리 조건은 치료제를 4개 개발하는 것 뿐이기에, 한 명의 플레이어가 같은 색의 도시 카드 5장을 모으는 것이 가장 중요합니다.
- 같은 위치에 있는 두 플레이어가 해당하는 도시의 카드만 교환할 수 있음을 명심해야 합니다.
- 자신의 캐릭터 능력을 십분 발휘해야만 합니다.
6a7f8deab9df7d6110ba88375c107bddad269846
Gamehelpagricola
0
274
1557
2023-11-25T16:03:49Z
2022JUN
9329
새 문서: [개요] 나만의 농장에 오신 것을 환영합니다. 아그리콜라를 플레이하며 여러분은 14 라운드를 거쳐, 거의 비어있던 공간에서 곡식과 야채가 자라나고 동물들을 기르며, 생기 가득한 농장으로 탈바꿈 시키고 가족의 생활환경을 개선하는 농부 가족이 되어볼 것입니다. 플레이어들은 점수를 올리기 위해 다양한 칸에서 자원을 모으고 농장을 업그레이드하는 등 다양...
wikitext
text/x-wiki
[개요]
나만의 농장에 오신 것을 환영합니다. 아그리콜라를 플레이하며 여러분은 14 라운드를 거쳐, 거의 비어있던 공간에서 곡식과 야채가 자라나고 동물들을 기르며, 생기 가득한 농장으로 탈바꿈 시키고 가족의 생활환경을 개선하는 농부 가족이 되어볼 것입니다. 플레이어들은 점수를 올리기 위해 다양한 칸에서 자원을 모으고 농장을 업그레이드하는 등 다양한 행동을 취하도록, 그들의 일꾼을 행동 판 위의 장소들에 배치하는 동시에 가족을 부양할 음식을 지불해야 합니다. 14 라운드 후 가장 많은 점수를 올린 플레이어가 승리합니다!
[게임 분석]
각 플레이어는 다음과 같은 다양한 자원을 획득할 수 있습니다.
음식: 주기적으로 가족을 먹이기 위해 필요합니다.
나무: 울타리, 외양간 짓기와 방 늘리기, 설비 제작 등을 위해 필요합니다.
점토: 대부분의 주요 설비를 얻고 흙 집으로 개조 하기 위해 필요합니다.
돌: 돌 집으로의 업그레이드와 일부 주요설비를 얻기 위해 필요합니다.
갈대: 방 늘리기, 집 개조하기와 일부 설비를 얻기 위해 필요합니다.
곡식과 채소: 농장에 심을 수 있습니다.
7개의 보조설비 카드와 7개의 직업 카드로 구성된 손 패
미플로 표현되는 일꾼들(2명으로 시작한 뒤 게임 중 추가 획득할 수 있습니다.)
각 플레이어는 각자 다음의 요소들로 구성되는 농장판을 갖습니다.
1. 여러 타일로 표현되는 집: 방의 개수와 그 재료가 가족의 수를 제한하고 게임 종료 후 점수 계산 때 추가 점수를 얻을 수 있습니다.
2. 목초지와 그 안의 가축들: 목초지는 울타리로 둘러 쌓여 구분되며 그 안의 가축들은 음식으로 요리하거나 득점을 위해 남겨둘 수 있습니다.
3. 보조/주요설비와 직업 카드는 사용 시 개인 농장 판 아래에 내려놓으며 다양한 능력으로 추가 행동을 하거나 점수를 얻을 수 있습니다.
중앙의 보드는 플레이어들이 사용할 수 있는 액션 칸으로 구성되며 각 라운드마다 새로운 액션이 사용 가능하게 개방됩니다.
설비 액션 칸을 통해 10개의 주요설비를 획득할 수 있으며 대부분 음식을 얻고 요리하는 능력을 가지고 있습니다.
[게임 진행]
아그리콜라는 14개 라운드를 진행합니다. 각 라운드 시작 시마다 일부 행동 칸은 자원이 쌓이며, 이전 판에 사용되지 않고 남아있는 자원이 있다면 삭제되지 않고 새로운 라운드의 자원을 합합니다. 또한, 새로운 행동 칸이 열립니다. 이 새로운 액션들은 6페이즈에 걸쳐 1단계에 한 칸씩 약간의 무작위성을 가지고(큰 틀에서는 규칙적입니다.) 개방됩니다. 그리고 선 말을 가진 플레이어부터 순서를 시작해 행동 판에 자신의 일꾼을 배치하고 즉시 배치된 칸의 행동을 수행합니다. 자신의 턴에는 또한, 제한없이 자신의 주요설비의 효과를 사용해 특정한 요리행동을 하거나 가축을 재배치할 수 있습니다. 선 플레이어가 일꾼을 배치하면 다음 플레이어의 차례입니다. 플레이어들은 각 플레이어들이 자신의 일꾼을 모두 배치할 때까지 돌아가며 일꾼을 배치합니다. 행동 판의 각 라운드 옆에 뿔나팔이 그려진 라운드가 끝날 때마다 수확을 진행합니다. 이후 새로운 라운드를 시작합니다.
<시작 행동>
게임 시작 시점에 다음의 행동을 할 수 있습니다.
농장 확장: 갈대 2개와 현재 집을 구성하는 재료 5개(첫 시작 집은 나무 집)를 지불하여 새로운 방 1개를 추가한다. 이때 새로운 방은 기존 방과 맞닿아 있는 칸에만 지을 수 있다. 그리고, 이후에 빈칸이나 울타리가 둘러진 목초지에 외양간 1개를 지을 수도 있다.
외양간은 빈칸에 지을 시 1마리의 가축을 키울 수 있고 목초지 안에 지을 시 그 목초지의 동물 수 제한을 2배로 늘린다.
회합 장소: 선 말을 가져간다. 이로 인해 다음 라운드의 선 플레이어가 된다. 이 행동 칸을 통해서만 선 플레이어가 될 수 있다. 만약 아무도 해당 라운드에 이 행동 칸에 일꾼을 놓지 않는다면 기존의 선 플레이어가 계속해서 선 플레이어가 된다. 보조 설비 1개를 그 가격을 지불하고 내려놓을 수 있다.
곡식 종자: 곡식 1개를 얻는다.
농지: 자신의 농장판에 밭 1개를 더한다. 이 밭은 첫번째 밭이 아닐 경우 기존의 밭에 인접하게 배치해야 한다.
교습: 직업 카드 1개를 내려놓는다. 첫번째 직업카드는 공짜이지만, 이후부터는 음식 1개를 지불해야 한다.
날품팔이: 음식 2개를 얻는다.
숲: 이 칸은 매 라운드의 시작마다 나무 3개가 추가된다. 일꾼을 올리면 이 칸의 모든 나무를 가져간다.
흙 채굴장: 이 칸은 매 라운드의 시작마다 흙 1개가 추가된다. 일꾼을 올리면 이 칸의 모든 흙을 가져간다.
낚시: 이 칸은 매 라운드의 시작마다 음식 1개가 추가된다. 일꾼을 올리면 이 칸의 모든 음식을 가져간다.
(위의 행동 칸은 2인 기준 개방되며 플레이어의 수에 따라 추가된다.)
<1페이즈 행동>
이 행동들은 1-4 라운드에 개방되며 정확한 순서는 무작위입니다.
설비: 1개의 주요/보조설비를 그 가격을 지불하고 얻는다.
울타리 치기: 가지고 있는 나무의 개수까지 울타리를 쳐 가축을 기를 목초지를 얻을 수 있다. 울타리를 칠때는 목초지의 4면이 모두 막혀있는 형태가 되어야 한다.
양 시장: 이 칸은 매 라운드의 시작마다 양 1마리가 추가된다. 일꾼을 올리면 이 칸의 모든 양을 가져간다.
곡식 활용: 가지고 있는 곡식과 채소를 비어있는 밭에 심을 수 있다. 곡식을 밭에 심으면 같은 밭에 곡식 2개를 즉시 추가한다. 수확 시기마다 이 곡식 1개를 가져온다. 채소는 동일한 방식으로 활용되지만 채소 1개를 밭에 추가한다는 점만이 다르다. 또한, 빵굽기 행동을 가능하게 하는 카드가 있다면 곡식 1개 당 카드가 지시하는 수의 음식으로 전환할 수 있다.
<2페이즈 행동>
이 행동들은 5-7 라운드에 개방되며 정확한 순서는 무작위입니다.
서부 채석장: 이 칸은 매 라운드의 시작마다 돌 1개가 추가된다. 일꾼을 올리면 이 칸의 모든 돌을 가져간다.
집 개조: 나무 집을 흙 집으로 개조하거나 흙 집을 돌 집으로 개조한다. 이를 위해 갈대 1개와 개조 결과가 되는 재료를 방 개수만큼 지불한다. 집 전체에 해당하는 재료를 가지고 있어야 사용할 수 있다. 방을 개별적으로 개조할 수는 없다. 추가로, 주요/보조 설비 1개를 그 가격을 지불하고 짓는다.
급하지 않은 가족 늘리기: 가족에 새로운 일꾼을 추가한다. 이 칸은 방 개수보다 가족의 수가 더 적을 때만 사용 가능하다. 새로운 일꾼은 다음 라운드부터 행동 칸에 배치할 수 있으며 이 행동 칸을 사용한 라운드가 수확이 있는 라운드일 때, 새로운 일꾼은 음식을 1개만 요구한다.
<3페이즈 행동>
이 행동들은 8-9 라운드에 개방되며 정확한 순서는 무작위입니다.
채소 종자: 채소 1개를 얻는다.
돼지 시장: 이 칸은 매 라운드의 시작마다 돼지 1마리가 추가된다. 일꾼을 올리면 이 칸의 모든 돼지를 가져간다.
<4페이즈 행동>
이 행동들은 10-11 라운드에 개방되며 정확한 순서는 무작위입니다.
동부 채석장: 이 칸은 매 라운드의 시작마다 돌 1개가 추가된다. 일꾼을 올리면 이 칸의 모든 돌을 가져간다.
양 시장: 이 칸은 매 라운드의 시작마다 양 1마리가 추가된다. 일꾼을 올리면 이 칸의 모든 양을 가져간다.
<5페이즈 행동>
이 행동들은 12-13 라운드에 개방되며 정확한 순서는 무작위입니다.
밭 경작: 농장 판에 밭 1개를 놓는다. 그리고 곡식 활용에서와 같이 보유한 곡식과 채소를 심는다.
급한 가족 늘리기: 가족에 새로운 일꾼을 더한다. 급하지 않은 가족 늘리기와 같은 방식이지만, 방 개수에 따른 가족 인원수 제한을 무시한다.
<6페이즈 행동>
이 행동은 14라운드에 개방된다.
농장 개조: 집을 개조하고 울타리를 짓는다. 집 개조와 울타리 치기에 적용되는 규칙이 각각 동일하게 적용된다.
[수확]
수확은 4,7,9,11,13,14 라운드가 종료되었을 때 즉시 진행합니다. 각각의 수확은 다음의 순서로 진행됩니다.
밭 페이즈: 각각의 플레이어는 각각의 밭에서 곡식, 채소 1개씩을 가져간다.
먹이기 페이즈: 각각의 플레이어는 각 일꾼마다 2개씩의 음식을(1인일 때는 3개를, 가족 늘리기 행동으로 해당 라운드에 추가된 일꾼은 1개) 지불해야 한다. 플레이어는 자유 행동(설비 효과, 직업 카드 효과로 인한 요리, 가축 재배치 등)을 하여 이 비용을 맞출 수 있다. 이 비용을 지불할 수 없을 경우 구걸 카드 1장을 가져가고 이는 점수 계산 시 -3점으로 계산된다.
번식 페이즈: 만약 양, 돼지, 소가 2마리 이상 있을 때 해당 동물 1마리를 얻는다. 이후 즉시 동물을 재배치할 수 있지만, 요리할 수는 없다.
[게임 종료]
게임은 14 라운드의 종료 후에 끝이 납니다. 이후 플레이어는 자신의 농장의 점수를 계산하고 가장 높은 점수를 기록한 플레이어가 승리합니다.
[점수 계산]
-1 점 1 점 2 점 3 점 4 점
|----------|----------|----------|----------|----------|
밭 타일 | 0-1 | 2 | 3 | 4 | 5+ |
목초지 | 0 | 1 | 2 | 3 | 4+ |
|----------|----------|----------|----------|----------|
곡식 | 0 | 1-3 | 4-5 | 6-7 | 8+ |
채소 | 0 | 1 | 2 | 3 | 4+ |
|----------|----------|----------|----------|----------|
양 | 0 | 1-3 | 4-5 | 6-7 | 8+ |
돼지 | 0 | 1-2 | 3-4 | 5-6 | 7+ |
소 | 0 | 1 | 2-3 | 4-5 | 6+ |
|----------|----------|----------|----------|----------|
_________________________________________________
| |
| 농장 판의 사용되지 않은 칸 1개 당 -1점 |
| 목초지 안 외양간과 흙 방 1개 당 1점 |
| 돌 방 1개 당 2점 |
| 가족 구성원 1명 당 3점 |
| |
| 구걸 카드 1장 당 -3점 |
| _ 카드에서 지시하는 점수들 |
| _ 보너스 점수들 |
| |
-------------------------------------------------
fcc2bcbdc446c7e2f6992c4c47e90f1d22dbfd37
1558
1557
2023-11-25T16:05:08Z
2022JUN
9329
줄 바꾸기가 안되었음.
wikitext
text/x-wiki
[개요]
나만의 농장에 오신 것을 환영합니다. 아그리콜라를 플레이하며 여러분은 14 라운드를 거쳐, 거의 비어있던 공간에서 곡식과 야채가 자라나고 동물들을 기르며, 생기 가득한 농장으로 탈바꿈 시키고 가족의 생활환경을 개선하는 농부 가족이 되어볼 것입니다. 플레이어들은 점수를 올리기 위해 다양한 칸에서 자원을 모으고 농장을 업그레이드하는 등 다양한 행동을 취하도록, 그들의 일꾼을 행동 판 위의 장소들에 배치하는 동시에 가족을 부양할 음식을 지불해야 합니다. 14 라운드 후 가장 많은 점수를 올린 플레이어가 승리합니다!
[게임 분석]
각 플레이어는 다음과 같은 다양한 자원을 획득할 수 있습니다.
음식: 주기적으로 가족을 먹이기 위해 필요합니다.
나무: 울타리, 외양간 짓기와 방 늘리기, 설비 제작 등을 위해 필요합니다.
점토: 대부분의 주요 설비를 얻고 흙 집으로 개조 하기 위해 필요합니다.
돌: 돌 집으로의 업그레이드와 일부 주요설비를 얻기 위해 필요합니다.
갈대: 방 늘리기, 집 개조하기와 일부 설비를 얻기 위해 필요합니다.
곡식과 채소: 농장에 심을 수 있습니다.
7개의 보조설비 카드와 7개의 직업 카드로 구성된 손 패
미플로 표현되는 일꾼들(2명으로 시작한 뒤 게임 중 추가 획득할 수 있습니다.)
각 플레이어는 각자 다음의 요소들로 구성되는 농장판을 갖습니다.
1. 여러 타일로 표현되는 집: 방의 개수와 그 재료가 가족의 수를 제한하고 게임 종료 후 점수 계산 때 추가 점수를 얻을 수 있습니다.
2. 목초지와 그 안의 가축들: 목초지는 울타리로 둘러 쌓여 구분되며 그 안의 가축들은 음식으로 요리하거나 득점을 위해 남겨둘 수 있습니다.
3. 보조/주요설비와 직업 카드는 사용 시 개인 농장 판 아래에 내려놓으며 다양한 능력으로 추가 행동을 하거나 점수를 얻을 수 있습니다.
중앙의 보드는 플레이어들이 사용할 수 있는 액션 칸으로 구성되며 각 라운드마다 새로운 액션이 사용 가능하게 개방됩니다.
설비 액션 칸을 통해 10개의 주요설비를 획득할 수 있으며 대부분 음식을 얻고 요리하는 능력을 가지고 있습니다.
[게임 진행]
아그리콜라는 14개 라운드를 진행합니다. 각 라운드 시작 시마다 일부 행동 칸은 자원이 쌓이며, 이전 판에 사용되지 않고 남아있는 자원이 있다면 삭제되지 않고 새로운 라운드의 자원을 합합니다. 또한, 새로운 행동 칸이 열립니다. 이 새로운 액션들은 6페이즈에 걸쳐 1단계에 한 칸씩 약간의 무작위성을 가지고(큰 틀에서는 규칙적입니다.) 개방됩니다. 그리고 선 말을 가진 플레이어부터 순서를 시작해 행동 판에 자신의 일꾼을 배치하고 즉시 배치된 칸의 행동을 수행합니다. 자신의 턴에는 또한, 제한없이 자신의 주요설비의 효과를 사용해 특정한 요리행동을 하거나 가축을 재배치할 수 있습니다. 선 플레이어가 일꾼을 배치하면 다음 플레이어의 차례입니다. 플레이어들은 각 플레이어들이 자신의 일꾼을 모두 배치할 때까지 돌아가며 일꾼을 배치합니다. 행동 판의 각 라운드 옆에 뿔나팔이 그려진 라운드가 끝날 때마다 수확을 진행합니다. 이후 새로운 라운드를 시작합니다.
<시작 행동>
게임 시작 시점에 다음의 행동을 할 수 있습니다.
농장 확장: 갈대 2개와 현재 집을 구성하는 재료 5개(첫 시작 집은 나무 집)를 지불하여 새로운 방 1개를 추가한다. 이때 새로운 방은 기존 방과 맞닿아 있는 칸에만 지을 수 있다. 그리고, 이후에 빈칸이나 울타리가 둘러진 목초지에 외양간 1개를 지을 수도 있다.
외양간은 빈칸에 지을 시 1마리의 가축을 키울 수 있고 목초지 안에 지을 시 그 목초지의 동물 수 제한을 2배로 늘린다.
회합 장소: 선 말을 가져간다. 이로 인해 다음 라운드의 선 플레이어가 된다. 이 행동 칸을 통해서만 선 플레이어가 될 수 있다. 만약 아무도 해당 라운드에 이 행동 칸에 일꾼을 놓지 않는다면 기존의 선 플레이어가 계속해서 선 플레이어가 된다. 보조 설비 1개를 그 가격을 지불하고 내려놓을 수 있다.
곡식 종자: 곡식 1개를 얻는다.
농지: 자신의 농장판에 밭 1개를 더한다. 이 밭은 첫번째 밭이 아닐 경우 기존의 밭에 인접하게 배치해야 한다.
교습: 직업 카드 1개를 내려놓는다. 첫번째 직업카드는 공짜이지만, 이후부터는 음식 1개를 지불해야 한다.
날품팔이: 음식 2개를 얻는다.
숲: 이 칸은 매 라운드의 시작마다 나무 3개가 추가된다. 일꾼을 올리면 이 칸의 모든 나무를 가져간다.
흙 채굴장: 이 칸은 매 라운드의 시작마다 흙 1개가 추가된다. 일꾼을 올리면 이 칸의 모든 흙을 가져간다.
낚시: 이 칸은 매 라운드의 시작마다 음식 1개가 추가된다. 일꾼을 올리면 이 칸의 모든 음식을 가져간다.
(위의 행동 칸은 2인 기준 개방되며 플레이어의 수에 따라 추가된다.)
<1페이즈 행동>
이 행동들은 1-4 라운드에 개방되며 정확한 순서는 무작위입니다.
설비: 1개의 주요/보조설비를 그 가격을 지불하고 얻는다.
울타리 치기: 가지고 있는 나무의 개수까지 울타리를 쳐 가축을 기를 목초지를 얻을 수 있다. 울타리를 칠때는 목초지의 4면이 모두 막혀있는 형태가 되어야 한다.
양 시장: 이 칸은 매 라운드의 시작마다 양 1마리가 추가된다. 일꾼을 올리면 이 칸의 모든 양을 가져간다.
곡식 활용: 가지고 있는 곡식과 채소를 비어있는 밭에 심을 수 있다. 곡식을 밭에 심으면 같은 밭에 곡식 2개를 즉시 추가한다. 수확 시기마다 이 곡식 1개를 가져온다. 채소는 동일한 방식으로 활용되지만 채소 1개를 밭에 추가한다는 점만이 다르다. 또한, 빵굽기 행동을 가능하게 하는 카드가 있다면 곡식 1개 당 카드가 지시하는 수의 음식으로 전환할 수 있다.
<2페이즈 행동>
이 행동들은 5-7 라운드에 개방되며 정확한 순서는 무작위입니다.
서부 채석장: 이 칸은 매 라운드의 시작마다 돌 1개가 추가된다. 일꾼을 올리면 이 칸의 모든 돌을 가져간다.
집 개조: 나무 집을 흙 집으로 개조하거나 흙 집을 돌 집으로 개조한다. 이를 위해 갈대 1개와 개조 결과가 되는 재료를 방 개수만큼 지불한다. 집 전체에 해당하는 재료를 가지고 있어야 사용할 수 있다. 방을 개별적으로 개조할 수는 없다. 추가로, 주요/보조 설비 1개를 그 가격을 지불하고 짓는다.
급하지 않은 가족 늘리기: 가족에 새로운 일꾼을 추가한다. 이 칸은 방 개수보다 가족의 수가 더 적을 때만 사용 가능하다. 새로운 일꾼은 다음 라운드부터 행동 칸에 배치할 수 있으며 이 행동 칸을 사용한 라운드가 수확이 있는 라운드일 때, 새로운 일꾼은 음식을 1개만 요구한다.
<3페이즈 행동>
이 행동들은 8-9 라운드에 개방되며 정확한 순서는 무작위입니다.
채소 종자: 채소 1개를 얻는다.
돼지 시장: 이 칸은 매 라운드의 시작마다 돼지 1마리가 추가된다. 일꾼을 올리면 이 칸의 모든 돼지를 가져간다.
<4페이즈 행동>
이 행동들은 10-11 라운드에 개방되며 정확한 순서는 무작위입니다.
동부 채석장: 이 칸은 매 라운드의 시작마다 돌 1개가 추가된다. 일꾼을 올리면 이 칸의 모든 돌을 가져간다.
양 시장: 이 칸은 매 라운드의 시작마다 양 1마리가 추가된다. 일꾼을 올리면 이 칸의 모든 양을 가져간다.
<5페이즈 행동>
이 행동들은 12-13 라운드에 개방되며 정확한 순서는 무작위입니다.
밭 경작: 농장 판에 밭 1개를 놓는다. 그리고 곡식 활용에서와 같이 보유한 곡식과 채소를 심는다.
급한 가족 늘리기: 가족에 새로운 일꾼을 더한다. 급하지 않은 가족 늘리기와 같은 방식이지만, 방 개수에 따른 가족 인원수 제한을 무시한다.
<6페이즈 행동>
이 행동은 14라운드에 개방된다.
농장 개조: 집을 개조하고 울타리를 짓는다. 집 개조와 울타리 치기에 적용되는 규칙이 각각 동일하게 적용된다.
[수확]
수확은 4,7,9,11,13,14 라운드가 종료되었을 때 즉시 진행합니다. 각각의 수확은 다음의 순서로 진행됩니다.
밭 페이즈: 각각의 플레이어는 각각의 밭에서 곡식, 채소 1개씩을 가져간다.
먹이기 페이즈: 각각의 플레이어는 각 일꾼마다 2개씩의 음식을(1인일 때는 3개를, 가족 늘리기 행동으로 해당 라운드에 추가된 일꾼은 1개) 지불해야 한다. 플레이어는 자유 행동(설비 효과, 직업 카드 효과로 인한 요리, 가축 재배치 등)을 하여 이 비용을 맞출 수 있다. 이 비용을 지불할 수 없을 경우 구걸 카드 1장을 가져가고 이는 점수 계산 시 -3점으로 계산된다.
번식 페이즈: 만약 양, 돼지, 소가 2마리 이상 있을 때 해당 동물 1마리를 얻는다. 이후 즉시 동물을 재배치할 수 있지만, 요리할 수는 없다.
[게임 종료]
게임은 14 라운드의 종료 후에 끝이 납니다. 이후 플레이어는 자신의 농장의 점수를 계산하고 가장 높은 점수를 기록한 플레이어가 승리합니다.
[점수 계산]
-1 점 1 점 2 점 3 점 4 점
|----------|----------|----------|----------|----------|
밭 타일 | 0-1 | 2 | 3 | 4 | 5+ |
목초지 | 0 | 1 | 2 | 3 | 4+ |
|----------|----------|----------|----------|----------|
곡식 | 0 | 1-3 | 4-5 | 6-7 | 8+ |
채소 | 0 | 1 | 2 | 3 | 4+ |
|----------|----------|----------|----------|----------|
양 | 0 | 1-3 | 4-5 | 6-7 | 8+ |
돼지 | 0 | 1-2 | 3-4 | 5-6 | 7+ |
소 | 0 | 1 | 2-3 | 4-5 | 6+ |
|----------|----------|----------|----------|----------|
_________________________________________________
| |
| 농장 판의 사용되지 않은 칸 1개 당 -1점 |
| 목초지 안 외양간과 흙 방 1개 당 1점 |
| 돌 방 1개 당 2점 |
| 가족 구성원 1명 당 3점 |
| |
| 구걸 카드 1장 당 -3점 |
| _ 카드에서 지시하는 점수들 |
| _ 보너스 점수들 |
| |
-------------------------------------------------
6ccc7feec39d011219b73b49e39919d5eed2b4b1
Gamehelpneutreeko
0
275
1559
2023-11-27T10:58:30Z
KoongFE
9334
새 문서: 목표 돌 세개를 가로 혹은 세로 혹은 대각선으로 정렬시켜야 합니다. 돌 세개는 연결돼 있어야 합니다. 움직임 돌은 상대의 돌을 만나거나 게임판의 가장자리에 닿을 때 까지 가로, 세로, 대각선 방향으로 미끄러집니다. 검은돌이 항상 먼저 움직입니다. 반복 똑같은 위치로 세번 반복되면 무승부가 선언됩니다.
wikitext
text/x-wiki
목표
돌 세개를 가로 혹은 세로 혹은 대각선으로 정렬시켜야 합니다.
돌 세개는 연결돼 있어야 합니다.
움직임
돌은 상대의 돌을 만나거나 게임판의 가장자리에 닿을 때 까지 가로, 세로, 대각선 방향으로 미끄러집니다.
검은돌이 항상 먼저 움직입니다.
반복
똑같은 위치로 세번 반복되면 무승부가 선언됩니다.
59349ebac38d6a6ca8a8a309407682e02f4168e4
1560
1559
2023-11-27T10:59:53Z
KoongFE
9334
wikitext
text/x-wiki
목표
돌 세개를 가로 혹은 세로 혹은 대각선으로 정렬시켜야 합니다.
돌 세개는 연결돼 있어야 합니다.
움직임
돌은 상대의 돌을 만나거나 게임판의 가장자리에 닿을 때 까지 가로, 세로, 대각선 방향으로 미끄러집니다.
검은돌이 항상 먼저 움직입니다.
반복
똑같은 위치로 세번 반복되면 무승부가 선언됩니다.
d8e335c9b30f87d4b840df97bc6bb7abd5a598f2
Gamehelpoasis
0
276
1561
2023-12-01T17:10:18Z
Badon7
9345
새 문서: 목표를 달성하려면 여행 카드를 내려놓거나, 훔치거나, 가져와서, 출발 도시 칼라 #13에서 오아시스 #0까지 내림차순으로 눈앞에서 플레이해야 합니다. 여행자 여러분, 이 에덴을 찾는 사람은 여러분 뿐만이 아닙니다! 다른 사람들을 견제하고 게임을 통제하는 효율성과 주의력을 기르세요! 강력한 동료를 모집하고 필수 장비를 얻음으로써 먼저 오아시스를 찾을 가...
wikitext
text/x-wiki
목표를 달성하려면 여행 카드를 내려놓거나, 훔치거나, 가져와서, 출발 도시 칼라 #13에서 오아시스 #0까지 내림차순으로 눈앞에서 플레이해야 합니다. 여행자 여러분, 이 에덴을 찾는 사람은 여러분 뿐만이 아닙니다! 다른 사람들을 견제하고 게임을 통제하는 효율성과 주의력을 기르세요! 강력한 동료를 모집하고 필수 장비를 얻음으로써 먼저 오아시스를 찾을 가능성을 높일 수 있습니다.
순서가 진행되는 동안 가능한 5가지 작업 중 하나만 선택해야 합니다:
탐색: 카드 2장을 내려놓습니다.
재활용 : 폐허의 카드 1장을 가져갑니다.
여행 : 여행 카드를 얼마든지 재생합니다.
모집 : 손에서 동료 카드 1장을 플레이하거나, 레이어에서 동료 카드 1장을 가져갑니다.
장비 : X카드를 폐기하여 1대의 X코스트 장비를 가져갑니다.
BGG 게임 페이지에서
bdb65f1a15157fea44ac59d3168f63ca8d8a5090
Gamehelpregicide
0
277
1562
2023-12-19T08:39:52Z
Kimchi the korean
9378
새 문서: 레지사이드에서 참가자들은 힘을 합쳐 12명의 강력한 적들을 물리쳐야 합니다. : 잭(J), 퀸(Q), 마지막으로 킹(K). 참가자들은 자기 손에 있는 카드의 내용을 알려주거나 어떤 카드를 내라는 식의 대화를 할 수 없고, 손에 남은 카드의 장수처럼 공개된 정보를 취합한 의견은 말할 수 있습니다. ▶[준비] 플레이 인원수에 따라 최대 손패 장수만큼의 카드를 나누어 줍니...
wikitext
text/x-wiki
레지사이드에서 참가자들은 힘을 합쳐 12명의 강력한 적들을 물리쳐야 합니다. : 잭(J), 퀸(Q), 마지막으로 킹(K).
참가자들은 자기 손에 있는 카드의 내용을 알려주거나 어떤 카드를 내라는 식의 대화를 할 수 없고, 손에 남은 카드의 장수처럼 공개된 정보를 취합한 의견은 말할 수 있습니다.
▶[준비]
플레이 인원수에 따라 최대 손패 장수만큼의 카드를 나누어 줍니다
참가자 수 | 사용 광대 장수 | 최대 손패 장수
1 0 8
2 0 7
3 1 6
4 2 5
▶[게임 방법]
각 차례는 4단계로 구성됩니다 :
1단계 - 카드를 내려놓거나 패스
2단계 - 슈트 능력 발동
3단계 - 현재의 적에게 피해를 주고 확인
4단계 - 현재의 적으로부터 피해 받기
▶[슈트 능력]
- 하트(♥): 버리는 더미로부터 회복
- 다이아몬드(♦): 카드 뽑기
- 클로버(♣): 이중 공격
- 스페이드(♠): 적의 공격력 감소
슈트의 능력은 같은 슈트를 가진 적에 대해서는 사용할 수 없습니다.
▶[적]
적 | 공격력 | 체력
잭(J) | 10 | 20
퀸(Q) | 15 | 30
킹(K) | 20 | 40
▶[게임 종료]
게임은 마지막 왕(K)을 물리치거나 어떤 참가자가 적으로부터
피해를 받은 뒤에 낼 카드가 부족해서 죽으면 끝납니다. 아울러
어떤 참가자가 카드를 사용할 수 없거나 패스조차 할 수 없는 상황이
되어도 참가자들의 패배로 끝납니다.
▶[특수 카드 조합]
- 광대 사용하기
1단계에서, 카드를 사용할 때 광대 카드를 사용할 수 있습니다 (단독으로만 사용).
광대의 공격력은 0입니다. 하지만 광대의 능력은 현재 적의 무적 상태를 무효화시킵니다.
다시 말해 적의 슈트가 없는 것으로 간주해, 이제부터 그 적에 대해 해당 슈트 능력을 발동시킬 수 있습니다.
광대를 사용한 뒤에는 3단계, 4단계를 건너뜁니다. 그러고 나서, 광대를 사용한 참가자가 선택한 참가자의 차례로 건너뜁니다.
- 호위 동물(A)
1단계에서, 호위 동물(A) 카드 1장을 사용할 수 있습니다.
하지만(광대를 제외한) 다른 카드 1장과 함께 사용도 가능합니다.
호위 동물은 공격력을 1로 간주해서, 함께 사용한 카드의 숫자에 더해지고, 사용한 동물의 슈트 능력도 발동됩니다.
- 콤보
1단계에서, 카드 1장을 사용하는 대신 같은 숫자의 카드를 2장 혹은 3장 혹은 4장까지 함께 사용할 수 있습니다.
다만 이때 사용한 카드 들의 숫자 총합이 10 이하여야 합니다. 이런 콤보에는 호위 동물카드를 더할 수 없습니다.
▶[1인용 게임]
다음 규칙을 따라서 혼자서 플레이 할 수도 있습니다 :
일반적인 방법처럼 게임을 준비합니다. 이때 광대 카드 2장은 따로 옆에 공개해서 빼놓습니다.
최대 손패 장수는 8장입니다. 게임은 일반적인 방법처럼 진행합니다. 한 차례가 끝나면 다시 새로운 차례를 진행합니다.
게임 중 광대 카드 1장을 뒤집어서 다음과 같은 새 능력을 사용할 수 있습니다
-손에 있는 카드 모두를 버리고 다시 8장을 뽑습니다. 다이아몬드에 무적인 적과 상대 중이라 해도 이 능력은 사용할 수 있습니다.
2장의 광대 카드를 공개로 놓고 시작하므로, 이 능력은 게임 중 딱 두 번 사용할 수 있습니다.
다른 용도로 능력을 사용하는 것이기 때문에 광대를 뒤집는다 해도 적의 무적 상태를 무효화 할 수는 없습니다.
광대의 새 능력은 1단계 시작 시 카드를 사용하기 전에, 혹은 4단계 시작 시 적으로부터 피해를 받기 바로 전에 사용할 수도 있습니다.
광대 2장을 사용하고 승리했다면 = 동메달
광대 1장을 사용하고 승리했다면 = 은메달
광대 0장을 사용하고 승리했다면 = 금메달
084d6c8c9dc351be95cd81f224297eac9a3ea78f
Tips cantstop
0
278
1563
2023-12-21T11:18:23Z
Heeonhappy
9382
새 문서: 보드의 중간에 있는 숫자가 더 쉽게 굴릴 수 있습니다. 6-7-8 또는 5-7-8 또는 6-7-9에서 토큰을 얻는 데 성공하면 전진할 수 있을 가능성이 높습니다. 욕심을 내서 이를 최대한 활용할 때입니다! 만약 당신이 2, 3, 11, 또는 12를 앞섰고, 판에 3개의 검은 토큰을 모두 가지고 있다면, 종종 즉시 멈추는 것이 좋다. 기억하라, 2-12를 앞으로 나아가면, 6-7-8을 앞으로 나아가는 것...
wikitext
text/x-wiki
보드의 중간에 있는 숫자가 더 쉽게 굴릴 수 있습니다. 6-7-8 또는 5-7-8 또는 6-7-9에서 토큰을 얻는 데 성공하면 전진할 수 있을 가능성이 높습니다. 욕심을 내서 이를 최대한 활용할 때입니다!
만약 당신이 2, 3, 11, 또는 12를 앞섰고, 판에 3개의 검은 토큰을 모두 가지고 있다면, 종종 즉시 멈추는 것이 좋다. 기억하라, 2-12를 앞으로 나아가면, 6-7-8을 앞으로 나아가는 것은 약 4수의 가치가 있다.
테이블 위에 세 번째 블랙 토큰을 놓는 것을 지연시킬 수 있을수록 (통상적으로) 더 오랫동안 안전하게 롤링을 계속할 수 있다. 이러한 이유로 처음 몇 번의 롤에서는 보통 두 개의 다른 트랙보다 한 트랙에서만 (특히 두 번 할 수 있는 경우) 전진하는 것이 바람직하다.
자신의 위험을 관리하기 위해 플레이하라. 자신이 훨씬 앞서 있다면 조금 더 안전하게 플레이하라. 자신이 많이 뒤처지면 위험을 피해서 얻을 수 있는 최선은 상당한 패배다.
어떤 플레이어가 획득한 트랙을 사용할 수 없음을 기억하십시오. 여기에는 승리한 트랙과 멈추면 승리하려고 하는 트랙이 포함됩니다. 따라서 게임의 후반 단계에서는 정체되어 턴을 잃기 쉽습니다.
당신의 전투를 고르십시오. 두 명 이상의 플레이어가 있는 게임(특히 세 명의 플레이어가 있는 게임)에서, 당신이 가는 모든 트랙에서 같은 상대와 싸우지 않도록 노력하십시오.
특히 보드 중앙 근처에서 한 번만 더 움직이면 된다고 해도 트랙을 얻을 것이라고는 절대로 생각하지 마십시오.
28의 법칙
한 연구자가 게임을 하는데 도움이 되는 휴리스틱을 발견했다(Michael Keller, 1986). 각 열에는 다음과 같은 점이 있다:
2와 12는 6점의 가치가 있다
3과 11은 5의 가치가 있다
4와 10은 4의 가치가 있다
5와 9는 3의 가치가 있다
6과 8은 2의 가치가 있다
7은 1의 가치가 있다
열에 검은 토큰을 진행할 때, 포인트의 수를 합계에 더해라. 검은 토큰을 처음 테이블 위에 올려놓을 때는 값을 두 배로 올려라. 합계가 28 이상이 될 때마다 멈추라.
좀 더 정교하게 다듬기 위해서 모든 검은 토큰이 홀수 열에 있으면 2를 더하고 짝수 열에 있으면 2를 뺀다. 모든 토큰이 8보다 작은 값에 있으면 4점을 더하고, 세 개 모두 6보다 큰 값에 있으면 4점을 더한다.
이 전략이 완벽하지 않다는 것을 기억하세요.
32108b96b94dd47e1cb15958ec6a1cec2ae82f60
Gamehelptickettoride
0
279
1564
2024-01-09T18:11:51Z
Idiosyncratic
9425
Creating 'ticket to ride' Korean rule description
wikitext
text/x-wiki
게임 목표
이 게임의 목표는 가장 높은 승점을 획득하는 것입니다. 점수는 다음 방법들을 통해 획득할 수 있습니다.
1. 지도상 인접한 2개 도시 간의 노선을 연결하는 방법
2. 목적지 카드에 나와 있는 두 도시 간의 노선을 연결하는 방법
3. 가장 긴 노선을 연결하는 방법
만일 소지하고 있는 목적지 카드에 나와 있는 두 도시 간의 노선 연결에 실패할 경우, 승점을 잃습니다.
게임 시작
각 플레이어는 기차 카드 덱에서 4장의 카드를 뽑아 무작위로 소지하게 됩니다.
그 뒤, 세 개의 목적지 카드를 확인한 후 두 개 이상의 목적지 카드를 가져가야 합니다. 플레이어는 이 목적지 카드를 게임이 끝날 때까지 공개할 수 없습니다. 목적지 카드 우하단에 있는 숫자는 그 카드의 점수를 의미합니다. 만일 플레이어가 그 카드에 나와 있는 두 도시 간의 노선을 연결한다면 쓰여 있는 만큼 점수를 챙기지만, 반대로 연결하지 못한다면 그만큼의 점수를 잃습니다.
목적지 카드를 선택한다면, 5장의 기차 카드가 추첨 구역에 일렬로 배치된 것을 알 수 있습니다. (목적지 카드를 선택하는 동안에도 추첨 구역 아래에 있는 작은 카드 5장을 통해 그 종류를 알 수 있습니다)
턴 진행
아래 세 개의 행동 중 단 한 가지의 행동만 할 수 있습니다.
1. 기차 카드 뽑기
카드덱이나 공개되어 있는 카드 5장 중 2장을 뽑거나, 공개되어 있는 카드 중 무지개색의 기관차 카드를 1장 뽑아갈 수 있습니다. 최대로 가질 수 있는 기차 카드의 개수에는 제한이 없습니다.
2. 노선 연결
노선은 한 도시에서 다른 도시로 연결하는 철도 노선입니다. 한 개의 노선을 연결하기 위해서는, 지도에 표시된 것과 동일한 색상의 기차 카드를(이때 회색은 원하는 통일된 색깔 한 가지를 의미합니다) 지도에 표시되어 있는 개수만큼 가지고 있으면 됩니다. 이때 한 장 이상의 무지개색 기관차 카드를 사용해도 무방합니다. 노선을 연결하기 위해서는 해당 노선을 클릭하면 됩니다. 아래에 나와 있듯이 노선이 길어질수록 더 큰 승점을 얻을 수 있습니다.
※주의할 점
2명이나 3명이 이 게임을 플레이하고 있다면 지도에 표시되어 있는 이중노선 중에 하나의 노선만을 사용할 수 있습니다. 플레이어는 두 도시를 연결하는 두 개의 노선 중 하나를 선택하여 연결할 수 있지만, 선택되지 않은 또 다른 노선은 다른 플레이어들이 사용할 수 없습니다.
3. 목적지 카드 뽑기
세 장의 목적지 카드를 뽑은 후 1장 이상의 목적지 카드를 반드시 가져가야 합니다.
기차 카드
-기차 카드는 총 110장으로 8종류의 일반 기차 카드(각각 12장)와 기관차 카드(14장)로 나뉩니다
-각 종류의 기차 카드 색깔은 그 색깔을 띠고 있는 노선에 사용할 수 있습니다. 보라색, 파란색, 주황색, 흰색, 초록색, 노란색, 검은색, 빨간색의 색상이 있습니다.
-기관차 카드는 무지개색을 띠고 있으며, 일종의 와일드카드로써 카드 색깔에 구애받지 않고 모든 노선 연결에 사용이 가능합니다.
-만일 기관차 카드가 5장의 공개된 카드 중 한 장에 포함되어 있다면, 그 기관차 카드를 뽑은 플레이어는 그 턴에 그 카드 한 장만을 뽑을 수 있습니다.
-기차 카드 한 장을 뽑은 뒤 교체된 카드가 기관차 카드라면, 플레이어는 그 기관차 카드를 뽑을 수 없습니다.
-만일 5장의 공개된 카드 중 기관차 카드가 3장 이상이라면, 그 즉시 모든 공개된 카드들이 버려지고 새로운 5장의 카드들이 공개됩니다.
-카드덱이 고갈된 경우, 버려진 카드들을 다시 섞어 새로운 뽑기 덱을 만듭니다.
목적지 카드
목적지 카드는 총 30장으로, 게임이 끝날 때까지 공개되지 않습니다.
플레이어가 목적지 카드에 표시되어 있는 두 도시를 연결하는 데 성공한다면, 게임 종료 시 목적지 카드에 표시되어 있는 만큼의 승점을 획득하게 됩니다.
두 도시를 연결하는 데 실패할 경우, 목적지 카드에 표시되어 있는 만큼의 승점을 차감하게 됩니다.
목적지 카드는 최종 승점 계산 단계 전까지 다른 플레이어들에게 공개되지 않습니다.
노선 점수
노선을 연결했을 때 받는 승점의 수는 해당 노선의 길이에 따라 달라집니다.
길이가 1칸일 때는 1점, 2칸일 때는 2점, 3칸일 때는 4점, 4칸일 때는 7점, 5칸일 때는 10점, 6칸일 때는 15점만큼의 승점을 얻을 수 있습니다.
게임 종료
마지막 라운드는 플레이어 중 그 누구라도 2개 이하의 기차만이 남았을 때 시작합니다. 각 플레이어(게임 종료를 유발한 플레이어도 포함)는 마지막 턴을 수행한 뒤, 최종 승점을 계산합니다.
각 플레이어는 완료한 목적지 카드들에 배당되어 있는 점수에 따라 승점을 얻고, 완료하지 못한 목적지 카드의 경우에도 똑같은 계산 방식으로 점수를 잃습니다.
지도에서 가장 긴 연결된 노선을 보유한 플레이어에게는 보너스 승점 10점을 부여합니다.
가장 많은 승점을 얻은 플레이어가 승리하게 됩니다!
확장팩
1910
기본판의 규칙을 따르지만, 새로운 1910 목적지 카드를 사용합니다.
최장 연결 노선 보너스가 가장 많은 수의 목적지 카드를 완료한 이에게 주는 '세계 여행자' 보너스로 대체됩니다.
메가 게임
최장 연결 노선 보너스와 '세계 여행자' 보너스가 둘 다 적용됩니다.
기본판의 목적지 카드와 1910 목적지 카드를 전부 사용합니다. (총 69장)
게임 시작 : 5장의 목적지 카드를 확인한 후 3장 이상의 목적지 카드를 가져가야 합니다.
목적지 카드 뽑기 : 4장의 목적지 카드 중 1장 이상의 목적지 카드를 가져가야 합니다.
대도시
모든 목적지 카드에 최소한 한 곳 이상의 대도시가 포함되어 있습니다. (시카고, 댈러스, 휴스턴, 로스앤젤레스, 마이애미, 뉴욕, 시애틀) 총 35장입니다.
게임 시작 : 5장의 목적지 카드를 확인한 후 3장 이상의 목적지 카드를 가져가야 합니다.
목적지 카드 뽑기 : 4장의 목적지 카드 중 1장 이상의 목적지 카드를 가져가야 합니다.
보너스가 없습니다.
5766fb063c2cf2f6124bfcf47ce98eb74b35f642
Gamehelpbombay
0
280
1565
2024-01-17T18:15:08Z
Postcard
9449
새 문서: 봄베이의 목표는 게임이 끝날 때 가장 많은 루피를 얻는 것입니다. 플레이어는 교역소에서 다양한 색상의 실크 베일을 구입하여 도시에 판매하고, 도시 토큰, 클라이언트 토큰을 수집하고 궁전을 건설하여 루피를 얻습니다. 플레이어는 3개의 액션 토큰을 가지고 차례를 시작합니다. 각 유형의 작업은 두 번 이상 수행할 수 있습니다(예외: 실크 더미 구매). 가능한...
wikitext
text/x-wiki
봄베이의 목표는 게임이 끝날 때 가장 많은 루피를 얻는 것입니다. 플레이어는 교역소에서 다양한 색상의 실크 베일을 구입하여 도시에 판매하고, 도시 토큰, 클라이언트 토큰을 수집하고 궁전을 건설하여 루피를 얻습니다.
플레이어는 3개의 액션 토큰을 가지고 차례를 시작합니다. 각 유형의 작업은 두 번 이상 수행할 수 있습니다(예외: 실크 더미 구매). 가능한 조치와 비용은 다음과 같습니다.
교차로에 따라 1개 또는 2개의 액션 토큰을 위해 인접한 교차로로 이동합니다.
색상/교역소에 따라 액션 토큰 1~2개와 루피 1~2개로 실크 베일을 구입하세요. *매 턴마다 실크 베일을 하나만 구입할 수 있습니다*
도시에서 실크 베일을 액션 토큰 1개에 판매합니다.
액션 토큰 1개와 실크 베일 1개로 궁전을 건설하세요.
플레이어는 또한 "자신의 재산을 통합"하고 행동을 수행하는 대신 은행에서 1루피를 얻을 수도 있습니다.
판매: 각 도시의 수요에 따라 루피를 받고 판매된 상품은 맨 아래로 이동합니다.
최고 - 4 루피
중간 - 3루피
하단 - 1루피 및 1개의 클라이언트 토큰.
보너스: 노란색 실크 베일은 추가 루피 1개에 판매되고 보라색 실크 베일은 추가 클라이언트 토큰 1개에 판매됩니다.
궁전: 궁전이 없는 교차로에 실크 베일 1개를 사용하여 자신의 색깔의 궁전을 지을 수 있으며 해당 위치에서 보너스 토큰을 받을 수 있습니다. 상대방이 당신의 궁전이 있는 곳으로 갈 때마다 당신은 은행에서 1루피를 받습니다.
보너스 토큰: 클라이언트 토큰 보너스, 도시 토큰 보너스, 2루피 보너스, 실크 베일 보너스(가장 왼쪽 시장에서 실크 베일을 선택하여 무료로 받으세요).
게임이 끝나면 플레이어는 대부분의 궁전 + 클라이언트 토큰에 따라 루피를 받습니다.
2인용 게임: 1위 = 4, 2위 = 0
3인용 게임: 1위 = 6, 2위 = 2, 3위 0
4인 게임: 1위 = 8, 2위 = 4, 3위 2, 4위 = 0
5인 게임: 1위 = 8, 2위 = 6, 3위 4, 4위 = 2, 5위 = 0
도시 토큰: 해당 도시에서 처음으로 실크 베일을 판매할 때 해당 도시에 해당하는 색상의 도시 토큰 1개를 받습니다. 단, 해당 색상의 토큰이 아직 남아 있어야 합니다. 보너스 도시 토큰은 해당 토큰이 있는 교차점에 궁전을 건설하여 얻을 수도 있습니다. 각 색상별로 하나의 도시 토큰만 가질 수 있습니다.
게임이 끝나면 플레이어는 다음을 받습니다.
1개 또는 2개의 다른 도시 토큰에 0루피
3개의 다른 도시 토큰에 4루피
4개의 다른 도시 토큰에 8루피
가장 많은 루피를 가진 플레이어가 승리합니다. 동점은 클라이언트 토큰 수에 따라 결정됩니다.
315331be891e4683a7fc86b03bfa3b2c94337ac2
Tips bunnykingdom
0
281
1566
2024-01-22T04:01:00Z
IlIIIlllIIlIIlIll
9461
새 문서: 팁: 1. 최대 40장의 카드를 뽑고 최대 200점을 획득하료고 헌다면 각 카드는 평균적으로 약 5점을 주어야 합니다. 2. 영지는 승리 포인트의 주요 원천입니다. 최소한 3가지 기본 자원과 많은 성을 모두 갖춘 영지를 얻어야 합니다. 3. 대부분의 양피지 카드는 황금당근을 5개 이상 제공하므로 이런 종류의 카드는 더 많이 가져가야 합니다. 야만인, 사회주의자 및 자유...
wikitext
text/x-wiki
팁:
1. 최대 40장의 카드를 뽑고 최대 200점을 획득하료고 헌다면 각 카드는 평균적으로 약 5점을 주어야 합니다.
2. 영지는 승리 포인트의 주요 원천입니다. 최소한 3가지 기본 자원과 많은 성을 모두 갖춘 영지를 얻어야 합니다.
3. 대부분의 양피지 카드는 황금당근을 5개 이상 제공하므로 이런 종류의 카드는 더 많이 가져가야 합니다. 야만인, 사회주의자 및 자유주의자, 외교관 및 관료와 같은 카드는 10점 이상을 주므로 확실한 선택입니다. 하지만 카드는 한 턴에 두개(2인일 경우엔 1개)만 가져올수 있다는 사실을 잊지마세요!
4. 영토 자체는 점수를 주지 않습니다. 특수 양피지 카드를 사용해도 5점 미만을 내는 경향이 있으므로 불필요한 영토 카드를 가져가서는 안 됩니다. 모든 자원과 성을 지을 수 있는 충분한 공간을 갖춘 다음 작은 영토에 집중하세요.
5. 나중에 사용하지 않을 수도 있는 영토를 지나치게 분산시키느라 첫 번째 턴을 낭비하지 마십시오. 대신 건물 카드와 양피지를 먼저 얻는 데 집중하세요. 몇 차례 턴을 지나면 다른 플레이어가 어디에 정착할 계획인지 알 수 있는데다가, 영토 경쟁이 덜 할 수 있는 빈 지역을 스스로 식별할 수 있습니다.
6. 너무 이르거나 너무 늦지 않게 기본 영토 건설을 시작해야 합니다. 응집력 있는 영토를 조기에 확보하는 것은 어렵고 몇 가지 포인트는 전체적으로 그다지 관련이 없습니다. 너무 늦게 여토 건설을 하면 득점할 수 있는 라운드가 거의 남지 않습니다. 그러니 2~3라운드를 노려보세요! 건물을 가장 커밋하기 좋은 시기기 때문이니까요.
af675ffd1e697cc1d10c555ebe676d139d8be0a9
Gamehelpyatzy
0
122
1567
1493
2024-03-23T05:07:38Z
Vnsse
9637
/* 막시 얏찌 */
wikitext
text/x-wiki
== 개요 ==
야찌는 각 턴마다 주사위를 굴려 '''포커'''처럼 족보를 만들어 점수를 얻어 경쟁하는 게임입니다.
== 진행 ==
매턴 마다 5개의 주사위를 굴립니다. 이후 원하는 주사위들을 최대 2번까지 더 굴릴 수 있습니다.
확정된 주사위를 아래의 족보에 따라 점수를 기입합니다. 각 영역에는 한번만 기입할 수 있습니다. 0점을 기입할 수도 있습니다.
규칙에 따라 기입할 수 있는 족보가 달라집니다.
== 규칙 ==
=== 야찌 ===
가장 기본이 되는 규칙입니다. 다른 곳에서 이 게임을 진행할 시 점수 계산이 다를 수 있습니다.
==== 상단 ====
상단에는 하나부터 여섯까지 족보가 있습니다. 주사위에서 해당 숫자의 눈금의 합을 점수로 계산합니다.
예를 들어, 2/6/3/4/6 조합으로는 여섯 칸에 12점을 기입할 수 있습니다.
상단에서 63점 이상을 내면 35점의 보너스 점수를 얻게됩니다. 보너스 점수가 중요한 야찌에서는 이것을 얻기 위해 각 주사위가 3개 이상이 되도록 하여 상단에 점수를 기입합니다.
==== 하단 ====
하단에는 아래와 같은 족보가 있습니다.
* 같은 숫자 3개 : 같은 숫자를 가진 주사위가 3개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 같은 숫자 4개 : 같은 숫자를 가진 주사위가 4개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 풀하우스 : 동일한 주사위 눈 한 종류가 3개, 다른 종류가 2개이거나 동일한 주사위 눈이 5개일 때, 25점을 기입합니다.
* 스몰 스트레이트 : 4개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4, 2/3/4/5, 3/4/5/6
* 라지 스트레이트 : 5개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4/5, 2/3/4/5/6
* 야찌 : 동일한 주사위 눈이 5개일 때, 50점을 기입합니다. 게임에서 야찌가 추가적으로 나올 때마다 보너스 점수 100점을 얻습니다.
* 찬스 : 조건 없이 모든 주사위 숫자 합계를 점수로 기입합니다. 족보를 완성하기 어려운 야찌에서 찬스를 이용해서 어려운 족보에 도전하는 것도 중요합니다.
=== 얌 ===
=== 요트 ===
=== 얏찌 ===
=== 막시 얏찌 무야호 ===
=== 크래그 ===
b336a0e5663a2c789a4cdecb335f1309fd9bbdca
1568
1567
2024-04-05T07:20:05Z
Norubal
9025
wikitext
text/x-wiki
== 개요 ==
야찌는 각 턴마다 주사위를 굴려 '''포커'''처럼 족보를 만들어 점수를 얻어 경쟁하는 게임입니다.
== 진행 ==
매턴 마다 5개의 주사위를 굴립니다. 이후 원하는 주사위들을 최대 2번까지 더 굴릴 수 있습니다.
확정된 주사위를 아래의 족보에 따라 점수를 기입합니다. 각 영역에는 한번만 기입할 수 있습니다. 0점을 기입할 수도 있습니다.
규칙에 따라 기입할 수 있는 족보가 달라집니다.
== 규칙 ==
=== 야찌 ===
가장 기본이 되는 규칙입니다. 다른 곳에서 이 게임을 진행할 시 점수 계산이 다를 수 있습니다.
==== 상단 ====
상단에는 하나부터 여섯까지 족보가 있습니다. 주사위에서 해당 숫자의 눈금의 합을 점수로 계산합니다.
예를 들어, 2/6/3/4/6 조합으로는 여섯 칸에 12점을 기입할 수 있습니다.
상단에서 63점 이상을 내면 35점의 보너스 점수를 얻게됩니다. 보너스 점수가 중요한 야찌에서는 이것을 얻기 위해 각 주사위가 3개 이상이 되도록 하여 상단에 점수를 기입합니다.
==== 하단 ====
하단에는 아래와 같은 족보가 있습니다.
* 같은 숫자 3개 : 같은 숫자를 가진 주사위가 3개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 같은 숫자 4개 : 같은 숫자를 가진 주사위가 4개 이상 존재할 때, 모든 주사위 숫자의 합계를 점수로 기입합니다.
* 풀하우스 : 동일한 주사위 눈 한 종류가 3개, 다른 종류가 2개이거나 동일한 주사위 눈이 5개일 때, 25점을 기입합니다.
* 스몰 스트레이트 : 4개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4, 2/3/4/5, 3/4/5/6
* 라지 스트레이트 : 5개의 연속된 숫자를 가진 주사위가 존재할 때, 30점을 기입합니다.
* 1/2/3/4/5, 2/3/4/5/6
* 야찌 : 동일한 주사위 눈이 5개일 때, 50점을 기입합니다. 게임에서 야찌가 추가적으로 나올 때마다 보너스 점수 100점을 얻습니다.
* 찬스 : 조건 없이 모든 주사위 숫자 합계를 점수로 기입합니다. 족보를 완성하기 어려운 야찌에서 찬스를 이용해서 어려운 족보에 도전하는 것도 중요합니다.
=== 얌 ===
=== 요트 ===
=== 얏찌 ===
=== 막시 얏찌 ===
=== 크래그 ===
247ce8ac1888b45b94be32b40a810cae93d8b31e
Tips terraformingmars
0
282
1569
2024-04-11T12:20:06Z
YUN3352
9688
새 문서: 주식회사 첫 번째 주요 결정은 회사의 선택입니다. 어떤 회사들은 다른 회사들보다 강하지만 이것은 플레이어의 수에 달려있을 수 있습니다. 예를 들어, 타르시스는 다른 플레이어들이 도시에서 경기를 할 때 이득을 얻고 많은 플레이어들과 잘 어울립니다. 그러나 광산 조합은 광물 매장지에서 타일을 치는 것을 좋아하고 이것은 그들을 위한 경쟁이 더 치열할 때...
wikitext
text/x-wiki
주식회사
첫 번째 주요 결정은 회사의 선택입니다. 어떤 회사들은 다른 회사들보다 강하지만 이것은 플레이어의 수에 달려있을 수 있습니다. 예를 들어, 타르시스는 다른 플레이어들이 도시에서 경기를 할 때 이득을 얻고 많은 플레이어들과 잘 어울립니다. 그러나 광산 조합은 광물 매장지에서 타일을 치는 것을 좋아하고 이것은 그들을 위한 경쟁이 더 치열할 때 더 어렵습니다.
카드
또 다른 큰 요인은 여러분이 처음으로 그리는 10장의 카드입니다. 여러분은 특히 여러분이 선택한 법인 카드를 가지고 갈 때 시너지 효과를 찾아야 합니다. 카드는 가져가기에 비싸기 때문에, 여러분은 카드가 비싸거나 곧 만족할 수 없는 요구 사항이 있기 때문에 일찍 할 수 없는 카드에 투자하는 것에 주의해야 합니다. 아쿠아퍼스와 같은 표준 프로젝트는 카드 없이도 할 수 있으므로 카드가 필수적이지 않다는 것을 명심하세요.
얼리 게임
초기 우선순위에는 수입과 생산을 개발하는 것, 마일스톤을 위해 경쟁하는 것, 그리고 열대 적도나 풍부한 광물 지대에 있는 화성의 좋은 부분에 도시를 설립하는 것이 포함됩니다.
게임 후기
게임 후반에, 초점은 경제 발전에서 승리 포인트(VP)를 득점하는 것으로 바뀔 것입니다. 상은 VP의 좋은 공급원이므로 상에 대한 고정이 있을 것 같을 때 구입해야 합니다.
d087d21f196fc8cc566c19d25a668832cb20283f
1570
1569
2024-04-11T12:20:54Z
YUN3352
9688
wikitext
text/x-wiki
주식회사
첫 번째 주요 결정은 회사의 선택입니다. 어떤 회사들은 다른 회사들보다 강하지만 이것은 플레이어의 수에 달려있을 수 있습니다. 예를 들어, 타르시스는 다른 플레이어들이 도시에서 경기를 할 때 이득을 얻고 많은 플레이어들과 잘 어울립니다. 그러나 광산 조합은 광물 매장지에서 타일을 치는 것을 좋아하고 이것은 그들을 위한 경쟁이 더 치열할 때 더 어렵습니다.
카드
또 다른 큰 요인은 여러분이 처음으로 그리는 10장의 카드입니다. 여러분은 특히 여러분이 선택한 법인 카드를 가지고 갈 때 시너지 효과를 찾아야 합니다. 카드는 가져가기에 비싸기 때문에, 여러분은 카드가 비싸거나 곧 만족할 수 없는 요구 사항이 있기 때문에 일찍 할 수 없는 카드에 투자하는 것에 주의해야 합니다. 아쿠아퍼스와 같은 표준 프로젝트는 카드 없이도 할 수 있으므로 카드가 필수적이지 않다는 것을 명심하세요.
얼리 게임
초기 우선순위에는 수입과 생산을 개발하는 것, 마일스톤을 위해 경쟁하는 것, 그리고 열대 적도나 풍부한 광물 지대에 있는 화성의 좋은 부분에 도시를 설립하는 것이 포함됩니다.
게임 후기
게임 후반에, 초점은 경제 발전에서 승리 포인트(VP)를 득점하는 것으로 바뀔 것입니다. 상은 VP의 좋은 공급원이므로 상에 대한 고정이 있을 것 같을 때 구입해야 합니다.
01152ec7c6e389e0ffa5b17189a427c8b1d8e0ff
Gamehelparknova
0
283
1571
2024-04-30T13:42:31Z
Yuza9087
9733
새 문서: 아크 노바에 오신 것을 환영합니다! 이 게임에서는 현대 동물원을 관리할 겁니다. 우리는 우리가 다룰 엄선된 동물들을 보호 구역에 넣는 것 뿐만 아니라, 스폰서를 모으고 보존 프로젝트를 지원할 겁니다. 매 턴마다 다섯 가지 중 하나의 행동을 선택하여 진행하며, 각 행동의 힘은 그 위치에 따라 달라집니다. 마지막으로 해당 행동을 선택한 지 얼마나 오래되었는...
wikitext
text/x-wiki
아크 노바에 오신 것을 환영합니다! 이 게임에서는 현대 동물원을 관리할 겁니다. 우리는 우리가 다룰 엄선된 동물들을 보호 구역에 넣는 것 뿐만 아니라, 스폰서를 모으고 보존 프로젝트를 지원할 겁니다. 매 턴마다 다섯 가지 중 하나의 행동을 선택하여 진행하며, 각 행동의 힘은 그 위치에 따라 달라집니다. 마지막으로 해당 행동을 선택한 지 얼마나 오래되었는지에 따라 힘이 강화됩니다. 당신의 점수는 매력(티켓 아이콘)과 보존(녹색 방패 아이콘)으로 측정되며, 이 두 트랙이 점수 트랙에서 교차하면 게임 종료가 됩니다. 그 후 한 번 더 라운드가 진행되고, 이 두 트랙이 서로 떨어져 있는 정도에 따라 가장 많은 점수를 획득한 플레이어가 게임에서 승리합니다!
턴에 해야 할 일
당신의 턴이 돌아오면, 당신 앞에 있는 다섯 가지 행동 카드 중 하나를 선택합니다. 이 행동에는 당신의 보드 아래쪽을 따라서 1부터 5까지의 힘이 할당됩니다. X 토큰을 사용하여 이 값을 더할 수 있습니다. 해당 행동을 수행한 후, 그것은 가장 왼쪽 위치로 이동하여 힘 1로 되며, 다른 모든 행동 카드를 오른쪽으로 한 칸씩 밀어냅니다.
특정 조건을 충족하면 이러한 행동 카드를 업그레이드하여 핑크색 면으로 뒤집을 수도 있습니다. 이 업그레이드된 행동들은 이전보다 더 효율적으로 사용할 수 있지만, 기본 형태와 동일한 규칙을 따릅니다.
건설 행동
기본 건설 행동은 크기가 1에서 5까지인 새로운 동물 우리나 특별 건물을 하나 건설할 수 있게 해줍니다. 동물을 동물원에 넣으려면 우리를 건설해야 합니다. 이를 위해, 각 타일 당 2 돈을 지불해야 합니다 (예를 들어, 크기 3인 우리나 애완동물원 특별 건물에 대해서도 6 돈을 지불해야 합니다). 모든 울타리와 건물은 이미 있는 울타리나 건물에 닿아 있어야 합니다. 울타리와 건물은 겹칠 수 없으며, 이미 동물원 지도에 인쇄된 바위나 물 공간 위에 타일을 놓을 수 없습니다.
일부 공간에는 보라색 삽과 "II"가 있습니다. 이러한 공간에는 건설 행동을 업그레이드할 때까지 건설할 수 없습니다.
다른 아이콘이 있는 타일은 "배치 보너스"입니다. 이러한 공간에 건물을 지을 때 해당하는 보너스를 얻습니다.
언제든지 지도 오른쪽 위 구석에 있는 작은 삽 아이콘을 클릭하여 가능한 모든 기본 울타리와 건물 모양을 볼 수 있습니다.
특별 건물
키오스크는 크기가 1인 짙은 회색 건물입니다. 키오스크는 소득 단계마다 주변 건물이나 차지된 울타리마다 1 돈을 제공합니다.
무대는 크기가 1인 분홍색 건물입니다. 무대를 놓으면 매력을 1 얻습니다.
애완동물원은 크기가 3인 특별한 울타리입니다. 일부 동물은 애완동물원에 놓여져야 하지만, 여러 동물이 건물 안에 공존할 수 있습니다. 애완동물원을 한 개만 건설할 수 있습니다.
업그레이드된 건설 행동:
행동 강도를 초과하지 않는 총 크기로 여러 가지 다른 울타리와/또는 건물을 건설할 수 있게 해줍니다. 예를 들어, 강도 5에서는 크기 3인 울타리, 크기 1인 울타리, 그리고 키오스크를 한꺼번에 건설할 수 있습니다 (하지만 크기 3인 울타리와 키오스크 두 개를 건설할 수는 없습니다; 모두 서로 다른 것이어야 합니다).
업그레이드된 건설 행동이 필요한 공간에 건설할 수 있게 해줍니다.
파충류 하우스와 대형 새 울타리를 건설할 수 있게 해줍니다. 애완동물원과 마찬가지로, 이 건물들은 특정 유형의 여러 동물을 수용할 수 있습니다. 파충류 하우스나 대형 새 울타리를 건설할 때, 해당 특별 건물에 수용될 수 있는 동물이 있다면 즉시 해당 건물로 옮길 수 있습니다. 그러면 해당 울타리가 다른 동물을 위해 비워지게 됩니다.
3f281ab1a75fec70c87872cef3a6179fd5bfc471
1572
1571
2024-04-30T13:51:06Z
Yuza9087
9733
wikitext
text/x-wiki
아크 노바에 오신 것을 환영합니다! 이 게임에서는 현대 동물원을 관리할 겁니다. 우리는 우리가 다룰 엄선된 동물들을 보호 구역에 넣는 것 뿐만 아니라, 스폰서를 모으고 보존 프로젝트를 지원할 겁니다. 매 턴마다 다섯 가지 중 하나의 행동을 선택하여 진행하며, 각 행동의 힘은 그 위치에 따라 달라집니다. 마지막으로 해당 행동을 선택한 지 얼마나 오래되었는지에 따라 힘이 강화됩니다. 당신의 점수는 매력(티켓 아이콘)과 보존(녹색 방패 아이콘)으로 측정되며, 이 두 트랙이 점수 트랙에서 교차하면 게임 종료가 됩니다. 그 후 한 번 더 라운드가 진행되고, 이 두 트랙이 서로 떨어져 있는 정도에 따라 가장 많은 점수를 획득한 플레이어가 게임에서 승리합니다!
턴에 해야 할 일
당신의 턴이 돌아오면, 당신 앞에 있는 다섯 가지 행동 카드 중 하나를 선택합니다. 이 행동에는 당신의 보드 아래쪽을 따라서 1부터 5까지의 힘이 할당됩니다. X 토큰을 사용하여 이 값을 더할 수 있습니다. 해당 행동을 수행한 후, 그것은 가장 왼쪽 위치로 이동하여 힘 1로 되며, 다른 모든 행동 카드를 오른쪽으로 한 칸씩 밀어냅니다.
특정 조건을 충족하면 이러한 행동 카드를 업그레이드하여 핑크색 면으로 뒤집을 수도 있습니다. 이 업그레이드된 행동들은 이전보다 더 효율적으로 사용할 수 있지만, 기본 형태와 동일한 규칙을 따릅니다.
건설 행동
기본 건설 행동은 크기가 1에서 5까지인 새로운 동물 우리나 특별 건물을 하나 건설할 수 있게 해줍니다. 동물을 동물원에 넣으려면 우리를 건설해야 합니다. 이를 위해, 각 타일 당 2 돈을 지불해야 합니다 (예를 들어, 크기 3인 우리나 애완동물원 특별 건물에 대해서도 6 돈을 지불해야 합니다). 모든 울타리와 건물은 이미 있는 울타리나 건물에 닿아 있어야 합니다. 울타리와 건물은 겹칠 수 없으며, 이미 동물원 지도에 인쇄된 바위나 물 공간 위에 타일을 놓을 수 없습니다.
일부 공간에는 보라색 삽과 "II"가 있습니다. 이러한 공간에는 건설 행동을 업그레이드할 때까지 건설할 수 없습니다.
다른 아이콘이 있는 타일은 "배치 보너스"입니다. 이러한 공간에 건물을 지을 때 해당하는 보너스를 얻습니다.
언제든지 지도 오른쪽 위 구석에 있는 작은 삽 아이콘을 클릭하여 가능한 모든 기본 울타리와 건물 모양을 볼 수 있습니다.
특별 건물
키오스크는 크기가 1인 짙은 회색 건물입니다. 키오스크는 소득 단계마다 주변 건물이나 차지된 울타리마다 1 돈을 제공합니다.
무대는 크기가 1인 분홍색 건물입니다. 무대를 놓으면 매력을 1 얻습니다.
애완동물원은 크기가 3인 특별한 울타리입니다. 일부 동물은 애완동물원에 놓여져야 하지만, 여러 동물이 건물 안에 공존할 수 있습니다. 애완동물원을 한 개만 건설할 수 있습니다.
업그레이드된 건설 행동:
행동 강도를 초과하지 않는 총 크기로 여러 가지 다른 울타리와/또는 건물을 건설할 수 있게 해줍니다. 예를 들어, 강도 5에서는 크기 3인 울타리, 크기 1인 울타리, 그리고 키오스크를 한꺼번에 건설할 수 있습니다 (하지만 크기 3인 울타리와 키오스크 두 개를 건설할 수는 없습니다; 모두 서로 다른 것이어야 합니다).
업그레이드된 건설 행동이 필요한 공간에 건설할 수 있게 해줍니다.
파충류 하우스와 대형 새 울타리를 건설할 수 있게 해줍니다. 애완동물원과 마찬가지로, 이 건물들은 특정 유형의 여러 동물을 수용할 수 있습니다. 파충류 하우스나 대형 새 울타리를 건설할 때, 해당 특별 건물에 수용될 수 있는 동물이 있다면 즉시 해당 건물로 옮길 수 있습니다. 그러면 해당 울타리가 다른 동물을 위해 비워지게 됩니다.
카드 행동
카드 행동은 더 많은 카드를 뽑을 수 있게 해줍니다. 이 행동의 강도에 따라 덱의 맨 위에서 하나 이상의 카드를 뽑거나 손에서 카드를 버릴 수도 있습니다 (방금 뽑은 것도 포함될 수 있습니다). 강도가 5일 때, 보드에서 한 장의 카드를 직접 손에 가져올 수도 있습니다. 손 제한 (3개 또는 해당 대학을 획득한 경우 5개)은 휴식 시에 강제로 적용될 것입니다. 또한 카드 행동을 사용하면 휴식 카운터가 2만큼 증가합니다.
업그레이드된 카드 행동
평판 범위 내의 보드에서 카드를 직접 뽑을 수 있게 해줍니다 (평판 마커의 왼쪽);
강도가 3 이상일 때 보드에서 카드를 "스냅"할 수 있게 해줍니다;
평판 범위가 9보다 높은 수준에 도달하고, 이에 따른 보너스가 제공됩니다;
특정 강도에서 주어진 강도에서 전체적으로 더 많은 카드를 뽑고 적은 수의 카드를 버릴 수 있게 해줍니다.
동물 행동
동물 행동은 동물 카드를 동물원에 플레이할 수 있게 해줍니다. 각 동물은 돈 비용과 함께 특정 크기 이상의 울타리를 필요로 합니다. 일부는 바위나 물에 접해야 할 수도 있습니다. 반드시 동물 카드의 왼쪽에 기재된 다른 선행 조건들을 주의하세요. 이러한 조건들은 항상 카드의 왼쪽 가장자리에 나열됩니다.
새로운 동물 카드를 플레이할 때, 해당 카드의 아래 가장자리에 나열된 보너스를 얻습니다. 이것이 제공하는 가장 일반적인 것은 다음과 같습니다.
매력 점수 (티켓 아이콘)
보존 점수 (녹색 방패 아이콘)
평판 점수 (검은 mortarboard 모자 아이콘)
대부분의 동물 카드에는 적어도 하나의 동물 유형 - 파충류, 새, 곰 등 -과 지역 - 아메리카, 아프리카, 유럽 등 -이 있습니다 (애완동물원 동물은 지역이 없습니다.) 이러한 아이콘들은 나중에 어떤 보존 프로젝트를 점수화할지 결정하는 데 매우 중요합니다.
업그레이드된 동물 행동
낮은 강도에서 여러 동물 카드를 플레이할 수 있게 해줍니다;
손에서만이 아니라 평판 범위 (평판 마커의 왼쪽)에서도 동물을 플레이할 수 있게 해줍니다;
동물의 왼쪽 가장자리에 동물 (II)를 선행 조건으로 나열한 특정 동물을 플레이할 수 있게 해줍니다.
후원자 행동
기본 후원자 행동은 손에서 후원자 (파란색) 카드를 플레이할 수 있게 해줍니다. 각 후원자 카드에 필요한 최소 행동 강도가 왼쪽 상단에 나열되어 있습니다. 이들은 일반적으로 플레이하는 데 돈을 지불할 필요는 없지만, 다른 요구 사항이 있을 수 있습니다. 후원자 카드는 당신에게 혜택을 주는 시간대를 알려주기 위해 색으로 구분됩니다:
- 노란색 상자는 카드를 플레이할 때 즉시 얻는 것을 나열합니다;
- 보라색 상자는 각 휴식마다 얻는 것을 나열합니다;
- 파란색 상자는 다른 조건을 충족할 때 얻는 것을 나열합니다 (예: 특정 아이콘을 플레이하거나 얻을 때);
- 갈색 상자는 게임 종료 시 얻는 것을 나열합니다.
플레이하고 싶은 후원자 카드가 없는 경우, 후원자 행동을 사용하여 돈을 얻고 행동의 강도와 같은 양만큼 휴식을 앞당길 수도 있습니다.
업그레이드된 후원자 행동
- 후원자 카드를 손에서가 아니라 평판 범위 (평판 마커의 왼쪽)의 보드에서 플레이할 수 있게 해줍니다;
- 후원자 카드를 플레이하는 대신, 행동의 강도의 두 배와 동일한 금액을 얻을 수 있게 해줍니다 (그리고 행동의 강도만큼 휴식을 앞당깁니다);
- 후원자 (II)를 요구 사항으로 나열한 후원자 카드를 플레이할 수 있게 해줍니다;
- 단일 행동으로 여러 후원자 카드를 플레이할 수 있게 해줍니다;
- 행동의 강도보다 1 단계 높은 강도의 후원자 카드를 플레이할 수 있게 해줍니다.
705603a0da950ef46c48217008338314b549f1a8
1573
1572
2024-04-30T13:56:36Z
Yuza9087
9733
문서를 비움
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
1574
1573
2024-04-30T13:58:18Z
Yuza9087
9733
[[Special:Contributions/Yuza9087|Yuza9087]] ([[User talk:Yuza9087|토론]])의 1573판 편집을 되돌림
wikitext
text/x-wiki
아크 노바에 오신 것을 환영합니다! 이 게임에서는 현대 동물원을 관리할 겁니다. 우리는 우리가 다룰 엄선된 동물들을 보호 구역에 넣는 것 뿐만 아니라, 스폰서를 모으고 보존 프로젝트를 지원할 겁니다. 매 턴마다 다섯 가지 중 하나의 행동을 선택하여 진행하며, 각 행동의 힘은 그 위치에 따라 달라집니다. 마지막으로 해당 행동을 선택한 지 얼마나 오래되었는지에 따라 힘이 강화됩니다. 당신의 점수는 매력(티켓 아이콘)과 보존(녹색 방패 아이콘)으로 측정되며, 이 두 트랙이 점수 트랙에서 교차하면 게임 종료가 됩니다. 그 후 한 번 더 라운드가 진행되고, 이 두 트랙이 서로 떨어져 있는 정도에 따라 가장 많은 점수를 획득한 플레이어가 게임에서 승리합니다!
턴에 해야 할 일
당신의 턴이 돌아오면, 당신 앞에 있는 다섯 가지 행동 카드 중 하나를 선택합니다. 이 행동에는 당신의 보드 아래쪽을 따라서 1부터 5까지의 힘이 할당됩니다. X 토큰을 사용하여 이 값을 더할 수 있습니다. 해당 행동을 수행한 후, 그것은 가장 왼쪽 위치로 이동하여 힘 1로 되며, 다른 모든 행동 카드를 오른쪽으로 한 칸씩 밀어냅니다.
특정 조건을 충족하면 이러한 행동 카드를 업그레이드하여 핑크색 면으로 뒤집을 수도 있습니다. 이 업그레이드된 행동들은 이전보다 더 효율적으로 사용할 수 있지만, 기본 형태와 동일한 규칙을 따릅니다.
건설 행동
기본 건설 행동은 크기가 1에서 5까지인 새로운 동물 우리나 특별 건물을 하나 건설할 수 있게 해줍니다. 동물을 동물원에 넣으려면 우리를 건설해야 합니다. 이를 위해, 각 타일 당 2 돈을 지불해야 합니다 (예를 들어, 크기 3인 우리나 애완동물원 특별 건물에 대해서도 6 돈을 지불해야 합니다). 모든 울타리와 건물은 이미 있는 울타리나 건물에 닿아 있어야 합니다. 울타리와 건물은 겹칠 수 없으며, 이미 동물원 지도에 인쇄된 바위나 물 공간 위에 타일을 놓을 수 없습니다.
일부 공간에는 보라색 삽과 "II"가 있습니다. 이러한 공간에는 건설 행동을 업그레이드할 때까지 건설할 수 없습니다.
다른 아이콘이 있는 타일은 "배치 보너스"입니다. 이러한 공간에 건물을 지을 때 해당하는 보너스를 얻습니다.
언제든지 지도 오른쪽 위 구석에 있는 작은 삽 아이콘을 클릭하여 가능한 모든 기본 울타리와 건물 모양을 볼 수 있습니다.
특별 건물
키오스크는 크기가 1인 짙은 회색 건물입니다. 키오스크는 소득 단계마다 주변 건물이나 차지된 울타리마다 1 돈을 제공합니다.
무대는 크기가 1인 분홍색 건물입니다. 무대를 놓으면 매력을 1 얻습니다.
애완동물원은 크기가 3인 특별한 울타리입니다. 일부 동물은 애완동물원에 놓여져야 하지만, 여러 동물이 건물 안에 공존할 수 있습니다. 애완동물원을 한 개만 건설할 수 있습니다.
업그레이드된 건설 행동:
행동 강도를 초과하지 않는 총 크기로 여러 가지 다른 울타리와/또는 건물을 건설할 수 있게 해줍니다. 예를 들어, 강도 5에서는 크기 3인 울타리, 크기 1인 울타리, 그리고 키오스크를 한꺼번에 건설할 수 있습니다 (하지만 크기 3인 울타리와 키오스크 두 개를 건설할 수는 없습니다; 모두 서로 다른 것이어야 합니다).
업그레이드된 건설 행동이 필요한 공간에 건설할 수 있게 해줍니다.
파충류 하우스와 대형 새 울타리를 건설할 수 있게 해줍니다. 애완동물원과 마찬가지로, 이 건물들은 특정 유형의 여러 동물을 수용할 수 있습니다. 파충류 하우스나 대형 새 울타리를 건설할 때, 해당 특별 건물에 수용될 수 있는 동물이 있다면 즉시 해당 건물로 옮길 수 있습니다. 그러면 해당 울타리가 다른 동물을 위해 비워지게 됩니다.
카드 행동
카드 행동은 더 많은 카드를 뽑을 수 있게 해줍니다. 이 행동의 강도에 따라 덱의 맨 위에서 하나 이상의 카드를 뽑거나 손에서 카드를 버릴 수도 있습니다 (방금 뽑은 것도 포함될 수 있습니다). 강도가 5일 때, 보드에서 한 장의 카드를 직접 손에 가져올 수도 있습니다. 손 제한 (3개 또는 해당 대학을 획득한 경우 5개)은 휴식 시에 강제로 적용될 것입니다. 또한 카드 행동을 사용하면 휴식 카운터가 2만큼 증가합니다.
업그레이드된 카드 행동
평판 범위 내의 보드에서 카드를 직접 뽑을 수 있게 해줍니다 (평판 마커의 왼쪽);
강도가 3 이상일 때 보드에서 카드를 "스냅"할 수 있게 해줍니다;
평판 범위가 9보다 높은 수준에 도달하고, 이에 따른 보너스가 제공됩니다;
특정 강도에서 주어진 강도에서 전체적으로 더 많은 카드를 뽑고 적은 수의 카드를 버릴 수 있게 해줍니다.
동물 행동
동물 행동은 동물 카드를 동물원에 플레이할 수 있게 해줍니다. 각 동물은 돈 비용과 함께 특정 크기 이상의 울타리를 필요로 합니다. 일부는 바위나 물에 접해야 할 수도 있습니다. 반드시 동물 카드의 왼쪽에 기재된 다른 선행 조건들을 주의하세요. 이러한 조건들은 항상 카드의 왼쪽 가장자리에 나열됩니다.
새로운 동물 카드를 플레이할 때, 해당 카드의 아래 가장자리에 나열된 보너스를 얻습니다. 이것이 제공하는 가장 일반적인 것은 다음과 같습니다.
매력 점수 (티켓 아이콘)
보존 점수 (녹색 방패 아이콘)
평판 점수 (검은 mortarboard 모자 아이콘)
대부분의 동물 카드에는 적어도 하나의 동물 유형 - 파충류, 새, 곰 등 -과 지역 - 아메리카, 아프리카, 유럽 등 -이 있습니다 (애완동물원 동물은 지역이 없습니다.) 이러한 아이콘들은 나중에 어떤 보존 프로젝트를 점수화할지 결정하는 데 매우 중요합니다.
업그레이드된 동물 행동
낮은 강도에서 여러 동물 카드를 플레이할 수 있게 해줍니다;
손에서만이 아니라 평판 범위 (평판 마커의 왼쪽)에서도 동물을 플레이할 수 있게 해줍니다;
동물의 왼쪽 가장자리에 동물 (II)를 선행 조건으로 나열한 특정 동물을 플레이할 수 있게 해줍니다.
후원자 행동
기본 후원자 행동은 손에서 후원자 (파란색) 카드를 플레이할 수 있게 해줍니다. 각 후원자 카드에 필요한 최소 행동 강도가 왼쪽 상단에 나열되어 있습니다. 이들은 일반적으로 플레이하는 데 돈을 지불할 필요는 없지만, 다른 요구 사항이 있을 수 있습니다. 후원자 카드는 당신에게 혜택을 주는 시간대를 알려주기 위해 색으로 구분됩니다:
- 노란색 상자는 카드를 플레이할 때 즉시 얻는 것을 나열합니다;
- 보라색 상자는 각 휴식마다 얻는 것을 나열합니다;
- 파란색 상자는 다른 조건을 충족할 때 얻는 것을 나열합니다 (예: 특정 아이콘을 플레이하거나 얻을 때);
- 갈색 상자는 게임 종료 시 얻는 것을 나열합니다.
플레이하고 싶은 후원자 카드가 없는 경우, 후원자 행동을 사용하여 돈을 얻고 행동의 강도와 같은 양만큼 휴식을 앞당길 수도 있습니다.
업그레이드된 후원자 행동
- 후원자 카드를 손에서가 아니라 평판 범위 (평판 마커의 왼쪽)의 보드에서 플레이할 수 있게 해줍니다;
- 후원자 카드를 플레이하는 대신, 행동의 강도의 두 배와 동일한 금액을 얻을 수 있게 해줍니다 (그리고 행동의 강도만큼 휴식을 앞당깁니다);
- 후원자 (II)를 요구 사항으로 나열한 후원자 카드를 플레이할 수 있게 해줍니다;
- 단일 행동으로 여러 후원자 카드를 플레이할 수 있게 해줍니다;
- 행동의 강도보다 1 단계 높은 강도의 후원자 카드를 플레이할 수 있게 해줍니다.
705603a0da950ef46c48217008338314b549f1a8
Gamehelpenemyanemone
0
284
1575
2024-05-01T02:27:08Z
Ufm
6353
새 문서: == Story == Look, this is a trick taking game featuring cards with numbers. There's not really a lot of theme here. But you've got to admit the name is pretty fun to say. Anyway, let's get to the game. == Components == 60 creature cards (6 suits, ranked 1-10) and 9 Anemone cards == Setup (3-6 players) == Choose one suit per player. Put any remaining cards back in the box. Shuffle the deck together and deal 10 cards to each player. Set the 9 Anemone cards within reach. The play...
wikitext
text/x-wiki
== Story ==
Look, this is a trick taking game featuring cards with numbers. There's not really a lot of theme here. But you've got to admit the name is pretty fun to say. Anyway, let's get to the game.
== Components ==
60 creature cards (6 suits, ranked 1-10) and 9 Anemone cards
== Setup (3-6 players) ==
Choose one suit per player. Put any remaining cards back in the box. Shuffle the deck together and deal 10 cards to each player. Set the 9 Anemone cards within reach. The player who is reading these rules is the start player.
(At 6p, remove the 1s and 10s from each suit and deal 8 to each player.)
== Game Play ==
The start player plays one card face up in front of them. Every other player in clockwise order must play a card face up in front of themself in a suit that has not yet been played into the trick. If a player cannot play a suit that has not been played, they discard a card from their hand into their score pile. The highest card played wins the trick and takes all cards played into their score pile. The lowest card played takes an Anemone card, which can be added to a card in a future trick to increase its value by 1 (multiple Anemone cards may be added at once). If there is a tie for the highest or lowest value, the later played breaks the tie.
At the end of the hand, once all cards have been played, players score one point per card taken. The 3s, 5s, and 8s of each suit are worth an extra point.
The player who has the lowest score at the end of the hand gains one +1 Anemone card. All Anemone cards carry over to the next hand.
The Anemone cards are +1 on one side and +2 on the other. If you have a +1 and would take another, flip it instead. It now has to be played as a +2. In a 6 player game, the lowest takes a +2 and the second lowest takes a +1. If they ever run out and a player should take one, the player with the most Anemone cards must give that player one of theirs.
The player with the highest score starts the next round. Play 4 rounds and the highest score wins! In case of a tie, the player with more Anemones remaining wins.
== 2 Player Variant ==
Use 4 suits. Remove the 1s and 10s. Shuffle and deal 8 cards to each player and place the remaining cards in a central deck.
Players take turns playing one card each into the trick until 4 cards have been played. All other rules apply, with each card needing to be a different suit.
Both players draw 2 cards into their hands before playing the next trick, until the deck is empty. If there are no cards to draw, skip that step and continue playing out the rest of the hand.
268fed9f38254ede69554d289bd1be02a9d04b82
1576
1575
2024-05-01T02:27:41Z
Ufm
6353
문서를 비움
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelpmojo
0
285
1577
2024-05-03T01:16:11Z
Victor Han
9740
가장 적은 포인트를 얻는 플레이어가 승리합니다
wikitext
text/x-wiki
요약
가장 적은 포인트를 얻은 플레이어가 승리합니다
준비
각 플레이어는 8장의 카드를 핸드로 가져갑니다.
시작 플레이어부터 모조 카드에 나와있는 방향대로 카드를 내며 순서를 진행합니다.
방법
1. 플레이 하는 숫자 카드가 중앙에 놓여진 카드보다 큰 숫자의 경우, 카드를 한 장 받습니다.
2. 같은 숫자의 카드를 낸 경우, 즉시 다른 카드 한 장을 더 냅니다.
3. 플레이어의 손에 들고있는 카드가 3장 이하가 된 경우, 모조 타임이 시작됩니다. 모조타임을 시작한 플레이어는 남은 카드를 뒷면으로 놓고 자신의 차례마다 차례를 진행하는 대신 남은 카드를 한 장씩 뒤집습니다.
모조타임을 시작하지 않은 플레이어는 차례가 될 때마다 모조타임을 시작한 플레이어의 카드가 모두 윗면을 향할 때 까지 계속해서 플레이 합니다.
(2인 경기에는 카드가 2장이 된 경우 모조타임이 발동됩니다)
4. 모조타임이 끝나면 남아있는 카드에 적힌 숫자를 합산하여 누가 가장 적은지 비교합니다. 이때, 만약 모조타임을 시작한 플레이어가 가장 적은 숫자가라면, 모조 카드를 +0면으로 가져가고 0점을 획득합니다. 반대의 경우, 패널티로 모조 카드를 +10 면으로 뒤집어 자신의 포인트에 10점을 추가합니다.
규칙
파란색 (0-1)
초록색 (2-4)
노란색 (5-7)
주황색 (8-10)
분홍색 (11-12)
모조타임이 끝나고 손에 남은 카드를 비교할 때 같은 색깔 카드가 여러장 있다면, 그 색깔 그룹의 가장 높은 숫자 카드 한 장만 숫자를 확인합니다.
만약 같은 숫자가 여러개라면, 숫자가 하나만 있는것으로 취급합니다.
가장 적은 포인트를 얻어 게임에서 승리하세요!
9e78666f86408e0d6aa3c4605e12505db47017a4
1580
1577
2024-05-17T11:57:43Z
Moonyo
7890
카드 종류에 따른 총 갯수
wikitext
text/x-wiki
요약
가장 적은 포인트를 얻은 플레이어가 승리합니다
준비
각 플레이어는 8장의 카드를 핸드로 가져갑니다.
시작 플레이어부터 모조 카드에 나와있는 방향대로 카드를 내며 순서를 진행합니다.
방법
1. 플레이 하는 숫자 카드가 중앙에 놓여진 카드보다 큰 숫자의 경우, 카드를 한 장 받습니다.
2. 같은 숫자의 카드를 낸 경우, 즉시 다른 카드 한 장을 더 냅니다.
3. 플레이어의 손에 들고있는 카드가 3장 이하가 된 경우, 모조 타임이 시작됩니다. 모조타임을 시작한 플레이어는 남은 카드를 뒷면으로 놓고 자신의 차례마다 차례를 진행하는 대신 남은 카드를 한 장씩 뒤집습니다.
모조타임을 시작하지 않은 플레이어는 차례가 될 때마다 모조타임을 시작한 플레이어의 카드가 모두 윗면을 향할 때 까지 계속해서 플레이 합니다.
(2인 경기에는 카드가 2장이 된 경우 모조타임이 발동됩니다)
4. 모조타임이 끝나면 남아있는 카드에 적힌 숫자를 합산하여 누가 가장 적은지 비교합니다. 이때, 만약 모조타임을 시작한 플레이어가 가장 적은 숫자가라면, 모조 카드를 +0면으로 가져가고 0점을 획득합니다. 반대의 경우, 패널티로 모조 카드를 +10 면으로 뒤집어 자신의 포인트에 10점을 추가합니다.
규칙
<nowiki/>: 모조타임이 끝나고 손에 남은 카드를 비교할 때 같은 색깔 카드가 여러장 있다면, 그 색깔 그룹의 가장 높은 숫자 카드 한 장만 숫자를 확인합니다.
만약 같은 숫자가 여러개라면, 숫자가 하나만 있는것으로 취급합니다.
카드 종류 및 갯수
파란색 (0-1)
4장씩
초록색 (2-4)
5장씩
노란색 (5-7)
6장씩
주황색 (8-10)
7장씩
분홍색 (11-12) 8장씩
가장 적은 포인트를 얻어 게임에서 승리하세요!
d4242f58b9cb897d20881bea090364b4d65d3657
1581
1580
2024-05-22T07:33:21Z
Thenamed
9763
wikitext
text/x-wiki
요약
가장 적은 포인트를 얻은 플레이어가 승리합니다
준비
각 플레이어는 8장의 카드를 핸드로 가져갑니다.
시작 플레이어부터 모조 카드에 나와있는 방향대로 카드를 내며 순서를 진행합니다.
방법
1. 플레이 하는 숫자 카드가 중앙에 놓여진 카드보다 큰 숫자의 경우, 카드를 한 장 받습니다.
2. 같은 숫자의 카드를 낸 경우, 즉시 다른 카드 한 장을 더 냅니다.
3. 플레이어의 손에 들고있는 카드가 3장 이하가 된 경우, 모조 타임이 시작됩니다. 모조타임을 시작한 플레이어는 남은 카드를 뒷면으로 놓고 자신의 차례마다 차례를 진행하는 대신 남은 카드를 한 장씩 뒤집습니다.
모조타임을 시작하지 않은 플레이어는 차례가 될 때마다 모조타임을 시작한 플레이어의 카드가 모두 윗면을 향할 때 까지 계속해서 플레이 합니다.
(2인 경기에는 카드가 2장이 된 경우 모조타임이 발동됩니다)
4. 모조타임이 끝나면 남아있는 카드에 적힌 숫자를 합산하여 누가 가장 적은지 비교합니다. 이때, 만약 모조타임을 시작한 플레이어가 가장 적은 숫자가라면, 모조 카드를 +0면으로 가져가고 0점을 획득합니다. 반대의 경우, 패널티로 모조 카드를 +10 면으로 뒤집어 자신의 포인트에 10점을 추가합니다.
규칙
<nowiki/>: 모조타임이 끝나고 손에 남은 카드를 비교할 때 같은 색깔 카드가 여러장 있다면, 그 색깔 그룹의 가장 높은 숫자 카드 한 장만 숫자를 확인합니다.
만약 같은 숫자가 여러개라면, 숫자가 하나만 있는것으로 취급합니다.
카드 종류 및 갯수
파란색 (0-1)
4장씩
초록색 (2-4)
5장씩
노란색 (5-7)
6장씩
주황색 (8-10)
7장씩
빨간색 (11-12)
8장씩
가장 적은 포인트를 얻어 게임에서 승리하세요!
f69f61713e9d7f8cc642a2d52fa6294801f7e5f7
1592
1581
2024-06-04T14:56:30Z
Moonyo
7890
wikitext
text/x-wiki
요약
가장 적은 포인트를 얻은 플레이어가 승리합니다
준비
각 플레이어는 8장의 카드를 핸드로 가져갑니다.
시작 플레이어부터 모조 카드에 나와있는 방향대로 카드를 내며 순서를 진행합니다.
방법
1. 플레이 하는 숫자 카드가 중앙에 놓여진 카드보다 큰 숫자의 경우, 카드를 한 장 받습니다.
2. 같은 숫자의 카드를 낸 경우, 즉시 다른 카드 한 장을 더 냅니다.
3. 플레이어의 손에 들고있는 카드가 3장 이하가 된 경우, 모조 타임이 시작됩니다. 모조타임을 시작한 플레이어는 남은 카드를 뒷면으로 놓고 자신의 차례마다 차례를 진행하는 대신 남은 카드를 한 장씩 뒤집습니다.
모조타임을 시작하지 않은 플레이어는 차례가 될 때마다 모조타임을 시작한 플레이어의 카드가 모두 윗면을 향할 때 까지 계속해서 플레이 합니다.
(2인 경기에는 카드가 2장이 된 경우 모조타임이 발동됩니다)
4. 모조타임이 끝나면 남아있는 카드에 적힌 숫자를 합산하여 누가 가장 적은지 비교합니다. 이때, 만약 모조타임을 시작한 플레이어가 가장 적은 숫자가라면, 모조 카드를 +0면으로 가져가고 0점을 획득합니다. 반대의 경우, 패널티로 모조 카드를 +10 면으로 뒤집어 자신의 포인트에 10점을 추가합니다.
규칙
<nowiki/>: 모조타임이 끝나고 손에 남은 카드를 비교할 때 같은 색깔 카드가 여러장 있다면, 그 색깔 그룹의 가장 높은 숫자 카드 한 장만 숫자를 확인합니다.
만약 같은 숫자가 여러개라면, 숫자가 하나만 있는것으로 취급합니다.
카드 종류 및 갯수
파란색 (0-1) - 4장씩
초록색 (2-4) - 5장씩
노란색 (5-7) - 6장씩
주황색 (8-10) - 7장씩
빨간색 (11-12) - 8장씩
가장 적은 포인트를 얻어 게임에서 승리하세요!
327117fe87996e1098e8796587073ba4c907f282
Gamehelploveletter
0
177
1578
1374
2024-05-03T12:06:17Z
Hongjumryea
9609
아첨꾼 4장에서 2장으로 변경
wikitext
text/x-wiki
승리 조건<br>
- 토큰을 다 모았을 경우 승리<br>
2명이 플레이 할 경우, 7개 / 3명이 플레이 할 경우, 5개 / 4명 이상이 플레이 할 경우, 4개<br>
토큰을 모으는 조건<br>
- 모든 인원이 탈락하고 1명만 남았을 경우<br>
- 덱카드가 다 떨어지고 두 명 이상 남았을 경우, 큰 숫자 카드를 가진 사람이 승리<br>
게임 방법<br>
1. 자신의 차례가 되면 덱에서 1장을 가져온다.<br>
2. 1장을 선택해서 모두에게 공개하고 공개한 카드의 기능을 사용한다.<br>
카드 기능<br>
1. 경비병(5장): 다른 플레이어 한 명을 골라 그 플레이어의 패를 추측합니다.(1번 카드를 지명할 수는 없습니다)만약 패를 맞췄다면 그 플레이어는 이번 라운드에서 탈락합니다.<br>
2. 성직자(2장): 다른 플레이어의 패를 봅니다.<br>
3. 남작(2장): 다른 플레이어 한 명을 골라 서로의 패를 비밀리에 비교합니다. 더 낮은 카드를 가진 플레이어는 이번 라운드에서 탈락합니다.<br>
4. 시녀(2장): 다음 턴까지 다른 플레이어들의 카드에 영향을 받지 않습니다.<br>
5. 왕자(2장): 한 명을 지목하여 패를 버리고 새 카드를 뽑게 합니다.(자신도 선택 가능)<br>
6. 왕(1장): 다른 플레이어와 패를 교환합니다.<br>
7. 백작부인(1장): 왕(6) 혹은 왕자(5) 카드와 이 카드를 함께 들고 있다면, 반드시 이카드를 버려야 합니다.<br>
8. 공주(1장):만약 당신이 이카드를 버리게 된다면, 당신은 이번 라운드에서 탈락합니다.<br>
5인 이상 추가 카드 기능<br>
0. 광대(1장): 다른 플레이어 한 명을 골라 광대 토큰을 줍니다. 만약 그 플레이어가 이번 라운드에서 승리하면 1점을 얻습니다.<br>
0. 암살자(1장): 이 카드를 쥐고있을 때 누군가 경비병으로 당신을 지목하면, 그 사람이 대신 라운드에서 탈락한 뒤 자신은 이카드를 버리고 새 카드를 뽑습니다.<br>
1. 경비병(추가 3장): 효과 동일, 일러스트가 다르다.<br>
2. 추기경(2장): 플레이어 2명을 골라 패를 교환시킨 뒤 둘 중 한 명의 패를 봅니다. <br>
3. 남작부인(2장) : 다른 플레이어 1~2명을 골라 패를 봅니다.<br>
4. 아첨꾼(2장): 원하는 플레이어 한 명을 고릅니다. 만약 다음에 사용되는 카드의 효과에서 플레이어를 선택해야 한다면, 이 카드로 고른 플레이어를 반드시 포합시켜야 합니다.<br>
5. 백작(2장): 라운드가 끝날 때, 쓴 카드더미에 이 카드가 있다면 내 카드의 가치가 +1 올라갑니다. 동률은 일반적으로 해결합니다.<br>
6. 치안관(1장): 당신이 탈락했을 때, 쓴 카드더미에 이 카드가 있다면 1점을 얻습니다.<br>
7. 왕태후(1장): 다른 플레이어 한 명을 골라 서로의 패를 비밀리에 비교합니다. 더 높은 카드를 가진 플레이어는 이번 라운드에서 탈락합니다.<br>
9. 주교(1장): 다른 플레이어 한 명을 골라 그 플레이어의 패를 추측합니다. (1번 카드를 지명할 수는 없습니다.) 만약 패를 맞췄다면 1점을 얻습니다. 상대방은 그 카드를 버리고 새 카드를 뽑을 수도 있습니다. 라운드가 끝날 때는 공주가 주교를 이깁니다.<br>
0ea3d5d2697191700ab6d14eaef79b415cfa1fac
Gamehelpevolution
0
286
1579
2024-05-05T16:51:09Z
Nanon65
9747
새 문서: 에볼루션의 목표는 종에게 먹이를 주고 개체 수를 늘리고 생존을 보장하기 위해 진화함으로써 최대 점수를 얻는 것입니다. 게임이 끝나면 플레이어는 자신의 종족이 게임 중에 먹은 음식, 생존한 종족의 개체 수 및 생존한 종족의 특성 카드에 대한 점수를 얻습니다. 게임플레이 에볼루션 게임은 다양한 라운드에 걸쳐 진행됩니다. 각 라운드에는 4단계가 있습니다...
wikitext
text/x-wiki
에볼루션의 목표는 종에게 먹이를 주고 개체 수를 늘리고 생존을 보장하기 위해 진화함으로써 최대 점수를 얻는 것입니다.
게임이 끝나면 플레이어는 자신의 종족이 게임 중에 먹은 음식, 생존한 종족의 개체 수 및 생존한 종족의 특성 카드에 대한 점수를 얻습니다.
게임플레이
에볼루션 게임은 다양한 라운드에 걸쳐 진행됩니다. 각 라운드에는 4단계가 있습니다.
수신카드
각 플레이어는 앞에 있는 각 종에 대해 3장의 카드와 1장의 카드를 받습니다. 이 단계에서 덱을 섞어야 한다면, 이번이 게임의 마지막 라운드가 될 것입니다.
식품 선택
워터링 홀에 얼굴을 아래로 하여 추가되는 손에서 비밀리에 1개의 특성 카드를 선택합니다.
이것들은 한 라운드에 얼마나 많은 식물성 식품을 사용할 수 있는지를 결정하기 위한 공급 단계에서 공개될 "식품 카드"입니다. 각 특성 카드의 오른쪽 하단에 있는 숫자는 식물성 식품의 양을 나타냅니다.
카드플레이
첫 번째 플레이어부터 원하는 만큼 특성 카드를 플레이하거나 다음 라운드를 위해 저장할 수 있습니다. 각 특성 카드로 (순서에 상관없이) 할 수 있는 일은 세 가지입니다:
• 특성 선택: 여러분은 여러분의 종 위에 특성 카드를 둘 수 있습니다. 한 종은 중복되는 특성 카드를 가지고 있지 않을 수도 있고, 3개 이하의 특성 카드를 가지고 있을 수도 있습니다(2인 게임에서 2개). 어떤 종이 이미 최대 개수의 특성 카드를 가지고 있다면, 플레이어는 그 종에 이미 있는 특성 카드를 먼저 버림으로써 그 종에 특성 카드를 할 수 있습니다.
먹이 주기
연못에 있는 식품 카드가 공개되고, 이 카드의 음식 번호가 추가되며, 식품더미에서 연못에 식물 식품이 그만큼 추가됩니다.
식품 카드의 합계가 음수이면, (가능하다면) 그만큼의 식물성 식품이 연못에서 제거됩니다. 공개한 식품 카드는 버립니다. 첫 번째 플레이어로 시작하여 시계 방향으로 계속 진행하여 종의 특성에 따라 각 플레이어는 배고픈 종 중 하나를 먹여야 합니다. 종의 개체수보다 적은 먹이를 먹으면 배고픈 종이 됩니다. 더 이상 배고프지 않은 종은 더 이상 추가적인 먹이를 받을 수 없습니다.
어떤 종이 음식을 먹을 때, 그것은 "1"개의 개체 수 트랙으로 시작하는 개체 수 트랙 위의 공간에 놓입니다. 어떤 음식을 먹든지 게임이 끝날 때 1점의 가치가 있을 것입니다.
• 비육식동물 : 물웅덩이에서 나온 식물성 식품 1개를 종 트랙에 추가합니다.
• 육식동물 : 육식동물은 절대 식물 먹이를 먹을 수 없습니다. 그들은 다른 종들을 공격함으로써 먹이를 먹습니다. 당신의 몸집이 그들의 몸집보다 크고 공격받은 종들의 방어적인 특성을 극복하기 위해 필요한 특성을 가지고 있다면 당신은 다른 종을 공격할 수 있습니다. 공격 후에, 당신은 보호구역에서 공격받은 종들의 몸집과 같은 고기 먹이를 추가하면 공격받은 종들의 개체 수는 1 감소합니다.
한 종의 개체수가 0에 도달하면, 그것은 멸종됩니다. 이 종에 의해 먹혔던 음식은 주인의 가방에 넣어지고, 그 종은 버려집니다(보드와 형질). 당신은 버려졌던 각각의 형질을 하나씩 철회합니다.모든 종들이 더 이상 배고프지 않거나 더 이상 먹이를 줄 수 없게 되면 먹이 주기 단계는 끝납니다.
어떤 종이 개체수와 같은 음식을 먹지 않았다면, 그 개체수는 먹은 음식의 양으로 줄어듭니다. 어떤 종이 어떤 음식도 먹지 않았다면, 그것은 멸종된 것입니다.
먹은 음식은 모두 각 선수의 가방에 넣어집니다.
살아남은 종이 없으면 새 종을 받습니다.
첫 번째 플레이어 토큰은 다음 플레이어에게 전달됩니다.
엔딩 및 스코어링
갑판이 다 떨어지면 게임은 그 라운드가 끝날 때 끝납니다.
1점당 1점을 받습니다:
• 당신의 가방에 들어있는 음식 토큰
• 살아남은 종의 개체 수
• 살아남은 종족의 특성 카드
동점일 경우 가장 많은 Trat Card 포인트를 획득한 플레이어가 승자가 됩니다. 동점일 경우 가장 많은 Population 포인트를 획득한 플레이어가 승자가 됩니다.
2인 선수 규칙
40 특성 카드는 게임 시작 시 덱에서 무작위로 제거됩니다.
당신의 종은 3개가 아닌 2개의 특성 카드만 가질 수 있습니다.
빠른 변형 및 6인 규칙
플레잉 카드 단계는 모든 플레이어가 동시에 플레이합니다.
8d1317209067bdfdeb4ae7ab9a5bd3938012de8e
Gamehelppaxrenaissance
0
287
1582
2024-05-26T15:07:45Z
Moonyo
7890
새 문서: 전투표 원정(campaign) 음모(CONSPIRACY) 농민봉기 (PEASANT REVOLT) 종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁) -토큰- 색깔 : 노(가톨릭:성전),초(이슬람:지하드),빨(개혁주의:종교개혁) 종류 : 대리인은 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 -나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가...
wikitext
text/x-wiki
전투표
원정(campaign)
음모(CONSPIRACY)
농민봉기 (PEASANT REVOLT)
종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-토큰-
색깔 : 노(가톨릭:성전),초(이슬람:지하드),빨(개혁주의:종교개혁)
종류 : 대리인은 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
a17ffea477612c7c11022dccf3d0f2bed32f7d34
1583
1582
2024-05-26T15:28:59Z
Moonyo
7890
wikitext
text/x-wiki
#요약표 참고
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력-
#토큰 설명
색깔 : 노(가톨릭:성전),초(이슬람:지하드),빨(개혁주의:종교개혁)
종류 : 대리인은 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
848f7084820cb3b385b010f3d60af9b0980ac4d7
1584
1583
2024-05-26T15:29:39Z
Moonyo
7890
wikitext
text/x-wiki
#요약표 참고
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력-
#토큰 설명
색깔 : 노(가톨릭:성전),초(이슬람:지하드),빨(개혁주의:종교개혁)
종류 : 대리인은 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
d38386a34c4c8ab89a31e5cbe1ec57ade4c048d6
1585
1584
2024-05-26T15:29:59Z
Moonyo
7890
wikitext
text/x-wiki
#요약표 참고
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력-
#토큰 설명
색깔 : 노(가톨릭:성전),초(이슬람:지하드),빨(개혁주의:종교개혁)
종류 : 대리인은 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
b11c02ec547c74bfc3771253270e8f9e25eb49d2
1586
1585
2024-05-26T15:51:21Z
Moonyo
7890
wikitext
text/x-wiki
#요약표 참고
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
-지도-
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
#토큰 설명
색깔 : 노(가톨릭:성전),초(이슬람:지하드),빨(개혁주의:종교개혁)
종류 : 대리인은 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
e08f1f2c16c043fad867b2ccdde51bdf6a4a9a61
1587
1586
2024-05-27T01:35:56Z
Moonyo
7890
wikitext
text/x-wiki
플레이어 손패는 총 2장이 한계 (일부 카드 능력으로 손패 제한해제가 있음)
#요약표 참고
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
#정권교체가 일어남 (정권교체 발생시 가능하면 3가지는 반드시 행동해야함. 1.제국카드 가져오기 2.경계 중 하나에 거류지 배치 3. 탄압받는 토큰 해방)
-지도-
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
서부(하얀색) / 동부(검은색)
#토큰 설명
색깔 : 노란색(가톨릭:성전),초록색(이슬람:지하드),빨간색(개혁주의:종교개혁)
종류 : 폰(플레이어 말) 배치할려는 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 또는 각 제국 경계에 놓음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
09c5724a6f499ff1ccb7e41e8e9a2494bf29f6b0
1588
1587
2024-05-27T01:37:37Z
Moonyo
7890
wikitext
text/x-wiki
#플레이어 손패는 총 2장이 한계 (일부 카드 능력으로 손패 제한해제가 있음)
@요약표 참고
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
#정권교체가 일어남 (정권교체 발생시 가능하면 3가지는 반드시 행동해야함. 1.제국카드 가져오기 2.경계 중 하나에 거류지 배치 3. 탄압받는 토큰 해방)
-지도-
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
서부(하얀색) / 동부(검은색)
@토큰 설명
색깔 : 노란색(가톨릭:성전),초록색(이슬람:지하드),빨간색(개혁주의:종교개혁)
종류 : 폰(플레이어 말) 배치할려는 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 또는 각 제국 경계에 놓음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
625212b15deb5ede6772f717479d74e68cfc3260
1589
1588
2024-05-27T01:39:11Z
Moonyo
7890
wikitext
text/x-wiki
플레이어 손패는 총 2장이 한계 (일부 카드 능력으로 손패 제한해제가 있음)
"요약표 참고"
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
#정권교체가 일어남 (정권교체 발생시 가능하면 3가지는 반드시 행동해야함. 1.제국카드 가져오기 2.경계 중 하나에 거류지 배치 3. 탄압받는 토큰 해방)
-지도-
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
서부(하얀색) / 동부(검은색)
"토큰 설명"
색깔 : 노란색(가톨릭:성전),초록색(이슬람:지하드),빨간색(개혁주의:종교개혁)
종류 :
-폰(플레이어 말) 배치할려는 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 또는 각 제국 경계에 놓음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
5c019d539e0f6ae62d652bc1b4c7511f2a1218a0
1590
1589
2024-06-01T05:35:26Z
Moonyo
7890
wikitext
text/x-wiki
"팍스 르네상스"
#승리조건 5가지 (제국승리 외 나머지 명성필요) 명성은 총 6종류 (법률,발견,(카톨릭,이슬람,개혁주의),후원자)
1.승리조건 4가지는 조건 활성화가 필요하며 "혜성카드" 구매하여 활성화를 하고 선언가능
(혜성카드: 동/서부 카드더미에서 2장 섞여있으며 12장 남았을때 부터 나옴)
2.나머지 승리조건 1가지는 시장카드더미가 다 떨어지면 게임이 종료되며 4가지 승리조건으로 게임이 안 끝날때 후원자 명성이 높은 쪽이 승리가 됨
(후원자 명성이 같으면 플로린 많은쪽)
플레이어 손패는 총 2장이 한계 (일부 카드 능력으로 손패 제한해제가 있음)
"요약표 참고"
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
#정권교체가 일어남 (정권교체 발생시 가능하면 3가지는 반드시 행동해야함. 1.제국카드 가져오기 2.경계 중 하나에 거류지 배치 3. 탄압받는 토큰 해방)
-지도-
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
서부(하얀색) / 동부(검은색)
"토큰 설명"
색깔 : 노란색(가톨릭:성전),초록색(이슬람:지하드),빨간색(개혁주의:종교개혁)
종류 :
-폰(플레이어 말) 배치할려는 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 또는 각 제국 경계에 놓음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
f69d24ebb424e525bc071cbc364b7cdf63e0d43c
1591
1590
2024-06-03T11:52:58Z
Moonyo
7890
wikitext
text/x-wiki
"팍스 르네상스"
#승리조건 5가지 (제국승리 외 나머지 명성필요) 명성은 총 6종류 (법률,발견,(카톨릭,이슬람,개혁주의),후원자)
1.승리조건 4가지는 조건 활성화가 필요하며 "혜성카드" 구매하여 활성화를 하고 선언가능
(혜성카드: 동/서부 카드더미에서 2장 섞여있으며 12장 남았을때 부터 나옴)
2.나머지 승리조건 1가지는 시장카드더미가 다 떨어지면 게임이 종료되며 4가지 승리조건으로 게임이 안 끝날때 후원자 명성이 높은 쪽이 승리가 됨
(후원자 명성이 같으면 플로린 많은쪽)
---
게임 진행
플레이어는 각 은행가를 하나씩 가져가고 순서에 따라 플로린을 차등 분배받는다
은행가 : 플레이어의 "문양" 및 "색깔"구분용으로 게임 영향은 없다.
플로린 : 게임 화폐
플레이어는 매턴마다 행동을 1~2 번 할수있으며 (무조건 한번은 진행) 할수있는 행동은 총 6가지
-1.카드구매 / 2.카드판매 / 3.카드사용 / 4.무역박람회 / 5.개인공간 활동 / 6.승리선언
#1.카드구매 : 위(서부),아래(동부) 시장에서 가능하며 맨 왼쪽(고정뒷면)부터 1플로린을 놓으면서 구매가능 (맨오른쪽 시장 더미)
플레이어가 구매하여 손에 가지고 있을 수 있는 카드는 총 2장이 한계 (일부 카드 능력으로 손패 제한해제가 있음)
#2.카드판매 : 카드 한장당 2플로린 (카드사용한 것도 가능)
#3.카드사용 : 개인공간으로 이동 (카드의 동(검)/서부(하얀) 시장에따라)
#4.무역박람회(플로린 획득)
설명 : 동/서부 교역로를 따라 교역선을 보내 시장의 뒷면카드에 쌓인 플로린을 획득 (시작시1 지나가는거류지마다1)
하나를 골라 쌓인 플로린에서 중국에서+2(2인 경우+1) 이 총 수익이 됨 (중국은 은행으로 플로린 공급처-해외시장)
-출발지점으로 교역소가 각각 3개 총 6개가 있으며 1개만 활성화 가능(비활성화는 검은색,하얀색으로 표시)
#5.개인공간 활동(카드의 현수막에 표시된 행동) 활동에는 총 9가지 종류가 있음.
활동을 선택하면 그 지역의 카드 수 만큼 원하는 순서대로 각 카드의 활동을 1개 선택하여 진행가능.
매턴마다 동부,서부 각각 1번씩만 할수있음(한턴에 같은지역의 활동을 연속으로 할수없음.)
"요약표 참고"
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
#정권교체가 일어남 (정권교체 발생시 가능하면 3가지는 반드시 행동해야함. 1.제국카드 가져오기 2.경계 중 하나에 거류지 배치 3. 탄압받는 토큰 해방)
-지도-
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
서부(하얀색) / 동부(검은색)
"토큰 설명"
색깔 : 노란색(가톨릭:성전),초록색(이슬람:지하드),빨간색(개혁주의:종교개혁)
종류 :
-폰(플레이어 말) 배치할려는 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 또는 각 제국 경계에 놓음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
3f5633ce224d1bd3751720a4f2814e40db109e3b
1593
1591
2024-06-04T15:55:12Z
Moonyo
7890
wikitext
text/x-wiki
===팍스 르네상스===
#승리조건 5가지 (제국승리 외 나머지 명성필요) 명성은 총 6종류 (법률,발견,(카톨릭,이슬람,개혁주의),후원자)
1.승리조건 4가지는 조건 활성화가 필요하며 "혜성카드" 구매하여 활성화를 하고 선언가능
(혜성카드: 동/서부 카드더미에서 2장 섞여있으며 12장 남았을때 부터 나옴)
2.나머지 승리조건 1가지는 시장카드더미가 다 떨어지면 게임이 종료되며 4가지 승리조건으로 게임이 안 끝날때 후원자 명성이 높은 쪽이 승리가 됨
(후원자 명성이 같으면 플로린 많은쪽)
===게임 진행===
플레이어는 각 은행가를 하나씩 가져가고 순서에 따라 플로린을 차등 분배받는다
은행가 : 플레이어의 "문양" 및 "색깔"구분용으로 게임 영향은 없다.
플로린 : 게임 화폐
플레이어는 매턴마다 행동을 1~2 번 할수있으며 (무조건 한번은 진행) 할수있는 행동은 총 6가지
-1.카드구매 / 2.카드판매 / 3.카드사용 / 4.무역박람회 / 5.개인공간 활동 / 6.승리선언
#1.카드구매 : 위(서부),아래(동부) 시장에서 가능하며 맨 왼쪽(고정뒷면)부터 1플로린을 놓으면서 구매가능 (맨오른쪽 시장 더미)
플레이어가 구매하여 손에 가지고 있을 수 있는 카드는 총 2장이 한계 (일부 카드 능력으로 손패 제한해제가 있음)
#2.카드판매 : 카드 한장당 2플로린 (카드사용한 것도 가능)
#3.카드사용 : 개인공간으로 이동 (카드의 동(검)/서부(하얀) 시장에따라)
#4.무역박람회(플로린 획득)
설명 : 동/서부 교역로를 따라 교역선을 보내 시장의 뒷면카드에 쌓인 플로린을 획득 (시작시1 지나가는거류지마다1)
하나를 골라 쌓인 플로린에서 중국에서+2(2인 경우+1) 이 총 수익이 됨 (중국은 은행으로 플로린 공급처-해외시장)
-출발지점으로 교역소가 각각 3개 총 6개가 있으며 1개만 활성화 가능(비활성화는 검은색,하얀색으로 표시)
#5.개인공간 활동(카드의 현수막에 표시된 행동) 활동에는 총 9가지 종류가 있음.
활동을 선택하면 그 지역의 카드 수 만큼 원하는 순서대로 각 카드의 활동을 1개 선택하여 진행가능.
매턴마다 동부,서부 각각 1번씩만 할수있음(한턴에 같은지역의 활동을 연속으로 할수없음.)
===요약표 참고===
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
#정권교체가 일어남 (정권교체 발생시 가능하면 3가지는 반드시 행동해야함. 1.제국카드 가져오기 2.경계 중 하나에 거류지 배치 3. 탄압받는 토큰 해방)
-지도-
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
서부(하얀색) / 동부(검은색)
"토큰 설명"
색깔 : 노란색(가톨릭:성전),초록색(이슬람:지하드),빨간색(개혁주의:종교개혁)
종류 :
-폰(플레이어 말) 배치할려는 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 또는 각 제국 경계에 놓음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
942805843b4df6f2a43a605d76f3428cd0b8e38e
1594
1593
2024-06-04T16:03:53Z
Moonyo
7890
wikitext
text/x-wiki
===팍스 르네상스===
#승리조건 5가지 (제국승리 외 나머지 명성필요) 명성은 총 6종류 (법률,발견,(카톨릭,이슬람,개혁주의),후원자)
1.승리조건 4가지는 조건 활성화가 필요하며 "혜성카드" 구매하여 활성화를 하고 선언가능
(혜성카드: 동/서부 카드더미에서 2장 섞여있으며 12장 남았을때 부터 나옴)
2.나머지 승리조건 1가지는 시장카드더미가 다 떨어지면 게임이 종료되며 4가지 승리조건으로 게임이 안 끝날때 후원자 명성이 높은 쪽이 승리가 됨
(후원자 명성이 같으면 플로린 많은쪽)
===게임 진행===
플레이어는 각 은행가를 하나씩 가져가고 순서에 따라 플로린을 차등 분배받는다
은행가 : 플레이어의 "문양" 및 "색깔"구분용으로 게임 영향은 없다.
플로린 : 게임 화폐
플레이어는 매턴마다 행동을 1~2 번 할수있으며 (무조건 한번은 진행) 할수있는 행동은 총 6가지
-1.카드구매 / 2.카드판매 / 3.카드사용 / 4.무역박람회 / 5.개인공간 활동 / 6.승리선언
#1.카드구매 : 위(서부),아래(동부) 시장에서 가능하며 맨 왼쪽(고정뒷면)부터 1플로린을 놓으면서 구매가능 (맨오른쪽 시장 더미)
플레이어가 구매하여 손에 가지고 있을 수 있는 카드는 총 2장이 한계 (일부 카드 능력으로 손패 제한해제가 있음)
#2.카드판매 : 카드 한장당 2플로린 (카드사용한 것도 가능)
#3.카드사용 : 개인공간으로 이동 (카드의 동(검)/서부(하얀) 시장에따라)
#4.무역박람회(플로린 획득)
설명 : 동/서부 교역로를 따라 교역선을 보내 시장의 뒷면카드에 쌓인 플로린을 획득 (시작시1 지나가는거류지마다1)
하나를 골라 쌓인 플로린에서 중국에서+2(2인 경우+1) 이 총 수익이 됨 (중국은 은행으로 플로린 공급처-해외시장)
-출발지점으로 교역소가 각각 3개 총 6개가 있으며 1개만 활성화 가능(비활성화는 검은색,하얀색으로 표시)
#5.개인공간 활동(카드의 현수막에 표시된 행동) 활동에는 총 9가지 종류가 있음.
활동을 선택하면 그 지역의 카드 수 만큼 원하는 순서대로 각 카드의 활동을 1개 선택하여 진행가능.
매턴마다 동부,서부 각각 1번씩만 할수있음(한턴에 같은지역의 활동을 연속으로 할수없음.)
===요약표 참고===
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
#정권교체가 일어남 (정권교체 발생시 가능하면 3가지는 반드시 행동해야함. 1.제국카드 가져오기 2.경계 중 하나에 거류지 배치 3. 탄압받는 토큰 해방)
-지도-
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
서부(하얀색) / 동부(검은색)
===토큰 설명===
색깔 : 노란색(가톨릭:성전),초록색(이슬람:지하드),빨간색(개혁주의:종교개혁)
종류 :
-폰(플레이어 말) 배치할려는 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 또는 각 제국 경계에 놓음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
4c03c0455ada7bddbf6a9de5659d20d435076c27
1595
1594
2024-06-04T16:05:25Z
Moonyo
7890
wikitext
text/x-wiki
===팍스 르네상스===
#승리조건 5가지 (제국승리 외 나머지 명성필요) 명성은 총 6종류 (법률,발견,(카톨릭,이슬람,개혁주의),후원자)
1.승리조건 4가지는 조건 활성화가 필요하며 "혜성카드" 구매하여 활성화를 하고 선언가능
(혜성카드: 동/서부 카드더미에서 2장 섞여있으며 12장 남았을때 부터 나옴)
2.나머지 승리조건 1가지는 시장카드더미가 다 떨어지면 게임이 종료되며 4가지 승리조건으로 게임이 안 끝날때 후원자 명성이 높은 쪽이 승리가 됨
(후원자 명성이 같으면 플로린 많은쪽)
===지도===
1.아라곤(ARAGON) / 2.동로마 비잔티움(BYZANTIUM) / 3.ENGLAND / 4.FRANCE / 5.HOLY ROMAN EMPIRE / 6.HUNGARY / 7.MAMLUK / 8.OTTOMAN / 9.PAPAL STATES / 10.PORTUGAL
서부(하얀색) / 동부(검은색)
===게임 진행===
플레이어는 각 은행가를 하나씩 가져가고 순서에 따라 플로린을 차등 분배받는다
은행가 : 플레이어의 "문양" 및 "색깔"구분용으로 게임 영향은 없다.
플로린 : 게임 화폐
플레이어는 매턴마다 행동을 1~2 번 할수있으며 (무조건 한번은 진행) 할수있는 행동은 총 6가지
-1.카드구매 / 2.카드판매 / 3.카드사용 / 4.무역박람회 / 5.개인공간 활동 / 6.승리선언
#1.카드구매 : 위(서부),아래(동부) 시장에서 가능하며 맨 왼쪽(고정뒷면)부터 1플로린을 놓으면서 구매가능 (맨오른쪽 시장 더미)
플레이어가 구매하여 손에 가지고 있을 수 있는 카드는 총 2장이 한계 (일부 카드 능력으로 손패 제한해제가 있음)
#2.카드판매 : 카드 한장당 2플로린 (카드사용한 것도 가능)
#3.카드사용 : 개인공간으로 이동 (카드의 동(검)/서부(하얀) 시장에따라)
#4.무역박람회(플로린 획득)
설명 : 동/서부 교역로를 따라 교역선을 보내 시장의 뒷면카드에 쌓인 플로린을 획득 (시작시1 지나가는거류지마다1)
하나를 골라 쌓인 플로린에서 중국에서+2(2인 경우+1) 이 총 수익이 됨 (중국은 은행으로 플로린 공급처-해외시장)
-출발지점으로 교역소가 각각 3개 총 6개가 있으며 1개만 활성화 가능(비활성화는 검은색,하얀색으로 표시)
#5.개인공간 활동(카드의 현수막에 표시된 행동) 활동에는 총 9가지 종류가 있음.
활동을 선택하면 그 지역의 카드 수 만큼 원하는 순서대로 각 카드의 활동을 1개 선택하여 진행가능.
매턴마다 동부,서부 각각 1번씩만 할수있음(한턴에 같은지역의 활동을 연속으로 할수없음.)
===요약표 참고===
-전투표-
1.원정(Campaign)
2.음모(CONSPIRACY)
3.농민봉기 (PEASANT REVOLT)
4.종교전쟁 (CRUSADE 교황령-카톨릭 십자군 성전/ JIHAD 이슬람교/ REFORMATION 천주교 종교개혁)
-활동-
1.이단심문(Inquisitor)
2.상업(Commerce)
3.참수(Behead)
4.징세(Tax)
5.탄압(Repress)
6.투표(Vote)
7.해적(Corsair)
8.공성(Siege)
9.원정(Campaign)
-일회성 능력- (폭탄모양이 위에있는 양피지)
1.무역(TRADE SHIFT) : (NOVGOROD / 홍해(RED SEA) / TIMBUKTU)
2.무역(TRADE SHIFT) : SPICE ISLANDE
3.농민봉기(PRASANT REVOLT) / 음모(CONSPIRACY)
4.배교(APOSTASY)
5.대관식(CORONATION)
#정권교체가 일어남 (정권교체 발생시 가능하면 3가지는 반드시 행동해야함. 1.제국카드 가져오기 2.경계 중 하나에 거류지 배치 3. 탄압받는 토큰 해방)
===토큰 설명===
색깔 : 노란색(가톨릭:성전),초록색(이슬람:지하드),빨간색(개혁주의:종교개혁)
종류 :
-폰(플레이어 말) 배치할려는 종류,색깔무시하고 어느 도시 칸이든 놓을 수 있음 또는 각 제국 경계에 놓음
-나이트(기사), 룩(귀족) / 지배계층 토큰 : 제국 도시에만 배치 가능. 전투가 발생 시 공격 및 방어에 사용
-비숍(이단심문관) : 지도 배치 안함
-해적 : 해상경계에만 배치. 교역선이 해적을 지나치면 1플로린을 중국(해외)로 보내버림
7f96ec39b45cae05736953db98043bd0eb3e95bd
Gamehelplure
0
288
1596
2024-06-04T17:29:49Z
Moonyo
7890
새 문서: ===비밀리에 주사위를 고르고 번갈아 가며 굴려서 물고기를 잡으세요. 더 큰 물고기를 낚기 위해 먼저 굴리기 위해 주사위를 적게 굴리세요. 여러분의 순서 전에 그들이 모두 잡히지 않기를 바랍니다.=== ====게임플레이==== 이 게임은 여러 라운드로 진행됩니다. 각 라운드는 3단계로 나뉩니다: 1. 스플래시: 물고기 3마리(또는 2-3명 중 2마리)를 공개합니다. 2. 캐스트:...
wikitext
text/x-wiki
===비밀리에 주사위를 고르고 번갈아 가며 굴려서 물고기를 잡으세요. 더 큰 물고기를 낚기 위해 먼저 굴리기 위해 주사위를 적게 굴리세요. 여러분의 순서 전에 그들이 모두 잡히지 않기를 바랍니다.===
====게임플레이====
이 게임은 여러 라운드로 진행됩니다. 각 라운드는 3단계로 나뉩니다:
1. 스플래시: 물고기 3마리(또는 2-3명 중 2마리)를 공개합니다.
2. 캐스트: 각 플레이어는 임의의 개수의 주사위를 선택하고 동시에 유인합니다.
3. 물고기: 각 플레이어는 가장 적은 주사위부터 가장 많은 주사위까지 자신이 선택한 주사위 수에 따라 차례로 굴려서 물고기를 잡습니다. 만약 두 명 이상의 플레이어가 같은 주사위 수를 보이면, 그들은 함께 굴립니다.
====물고기 굴리기====
1. 주사위를 굴리고 선택적으로 플레이한 모든 조정 미끼를 사용합니다.
2. 당신은 당신의 롤이 적어도 어획량에 추가되고 그것이 가지고 있는 어떤 요구 사항도 충족하면 물고기를 잡을 수 있습니다. 그 물고기들을 당신의 점수 더미에 엎어서 잡으세요.
3. 최소 1마리 이상의 물고기를 잡았을 경우, 플레이한 모든 부스트 미끼를 점수 더미 근처에 놓습니다
4. 나머지 미끼는 버립니다. 물고기를 잡지 않았다면 1개의 미끼를 그립니다.
5. 굴린 특별한 주사위를 화면 앞에 놓습니다.
Rolling Together: 같은 개수의 주사위를 동시에 던지는 플레이어입니다. 둘 다 물고기를 잡을 수 있다면, 합계가 낮은 플레이어가 물고기를 잡습니다. 동점이 되면, 아무도 물고기를 잡지 못합니다(중간에 놔둡니다).
루레스
주사위로 공개하는 미끼를 사용할 수 있습니다(보관한 미끼가 아님). 버려지는 미끼는 폐기 더미에 넣고 드로우 더미가 떨어지면 섞기만 합니다.
루어에는 3가지 종류가 있습니다:
- 조정: 주사위 숫자를 1만큼 위 또는 아래로 조정합니다. 여러 개의 미끼로 주사위를 조정할 수 있습니다. 일단 물고기를 잡으면 주사위를 조정할 수 없습니다.
- 엑스트라 다이: 표시된 번호를 롤에 추가하고 캐치 요구 사항에 대해 다이로 처리합니다. 턴 오더에 대한 다이로 계산되지 않으며 조정할 수 없습니다.
- 부스트: 물고기를 잡으면 2VP를 획득합니다. 물고기 1마리를 잡으면 모든 부스트를 획득합니다.
스페셜 주사위
굴리는 각각의 특별한 다이는 일반 다이와 같은 어획 요구 사항을 충족할 수 있습니다. 낚시 후 화면 앞에 배치하여 1라운드 동안 다시 사용할 수 없음을 보여주어야 합니다. 다음 라운드에 돌려주세요.
생선이 떨어짐
마지막 페이스업 물고기가 잡히면 아직 굴리지 않은 모든 사람이 자신이 플레이한 모든 미끼를 버리고 1개의 미끼를 추첨합니다. 그런 다음 주사위를 반환합니다(특별한 주사위는 여전히 앞에 있습니다).
게임 종료
마지막 물고기가 덱에서 뽑히면 현재 라운드를 끝내고 게임을 종료합니다. 각 플레이어는 모든 물고기에 VP를 득점하고 점수 더미를 늘립니다. 가장 많은 VP를 가진 플레이어가 이깁니다.
동점일 경우 물고기가 가장 적은 동점자가 승리합니다. 동점일 경우 승리를 공유합니다.
b8c45d4386861e45167212f98126eca5fd51d9b6
1597
1596
2024-06-04T17:54:59Z
Moonyo
7890
wikitext
text/x-wiki
====비밀리에 주사위를 고르고 번갈아 가며 굴려서 물고기를 잡으세요.
더 큰 물고기를 낚기 위해 먼저 굴리기 위해 주사위를 적게 굴리세요.
여러분의 순서 전에 그들이 모두 잡히지 않기를 바랍니다.====
====게임플레이====
이 게임은 여러 라운드로 진행됩니다. 각 라운드는 3단계로 나뉩니다:
1. 스플래시: 물고기 3마리(또는 2-3명 중 2마리)를 공개합니다.
2. 캐스트: 각 플레이어는 임의의 개수의 주사위를 선택하고 동시에 유인합니다.
3. 물고기: 각 플레이어는 가장 적은 주사위부터 가장 많은 주사위까지 자신이 선택한 주사위 수에 따라 차례로 굴려서 물고기를 잡습니다.
만약 두 명 이상의 플레이어가 같은 주사위 수를 보이면, 그들은 함께 굴립니다.
====물고기 굴리기====
1. 주사위를 굴리고 선택적으로 플레이한 모든 조정 미끼를 사용합니다.
2. 당신은 당신의 롤이 적어도 어획량에 추가되고 그것이 가지고 있는 어떤 요구 사항도 충족하면 물고기를 잡을 수 있습니다. 그 물고기들을 당신의 점수 더미에 엎어서 잡으세요.
3. 최소 1마리 이상의 물고기를 잡았을 경우, 플레이한 모든 부스트 미끼를 점수 더미 근처에 놓습니다
4. 나머지 미끼는 버립니다. 물고기를 잡지 않았다면 1개의 미끼를 그립니다.
5. 굴린 특별한 주사위를 화면 앞에 놓습니다.
Rolling Together: 같은 개수의 주사위를 동시에 던지는 플레이어입니다. 둘 다 물고기를 잡을 수 있다면, 합계가 낮은 플레이어가 물고기를 잡습니다. 동점이 되면, 아무도 물고기를 잡지 못합니다(중간에 놔둡니다).
루레스
주사위로 공개하는 미끼를 사용할 수 있습니다(보관한 미끼가 아님). 버려지는 미끼는 폐기 더미에 넣고 드로우 더미가 떨어지면 섞기만 합니다.
루어에는 3가지 종류가 있습니다:
- 조정: 주사위 숫자를 1만큼 위 또는 아래로 조정합니다. 여러 개의 미끼로 주사위를 조정할 수 있습니다. 일단 물고기를 잡으면 주사위를 조정할 수 없습니다.
- 엑스트라 다이: 표시된 번호를 롤에 추가하고 캐치 요구 사항에 대해 다이로 처리합니다. 턴 오더에 대한 다이로 계산되지 않으며 조정할 수 없습니다.
- 부스트: 물고기를 잡으면 2VP를 획득합니다. 물고기 1마리를 잡으면 모든 부스트를 획득합니다.
스페셜 주사위
굴리는 각각의 특별한 다이는 일반 다이와 같은 어획 요구 사항을 충족할 수 있습니다. 낚시 후 화면 앞에 배치하여 1라운드 동안 다시 사용할 수 없음을 보여주어야 합니다. 다음 라운드에 돌려주세요.
생선이 떨어짐
마지막 페이스업 물고기가 잡히면 아직 굴리지 않은 모든 사람이 자신이 플레이한 모든 미끼를 버리고 1개의 미끼를 추첨합니다. 그런 다음 주사위를 반환합니다(특별한 주사위는 여전히 앞에 있습니다).
====게임 종료====
마지막 물고기가 덱에서 뽑히면 현재 라운드를 끝내고 게임을 종료합니다. 각 플레이어는 모든 물고기에 VP를 득점하고 점수 더미를 늘립니다. 가장 많은 VP를 가진 플레이어가 이깁니다.
동점일 경우 물고기가 가장 적은 동점자가 승리합니다. 동점일 경우 승리를 공유합니다.
74cf65d9f4585b503efb191a0146ed2d3232a0b4
Gamehelpburglebros
0
289
1598
2024-06-06T14:30:41Z
K-oreo
9745
새 문서: - 플레이 방법 버글 브라더스는 타일 탐색과 문제 해결 기능을 갖춘 협동 로그라이크 퍼즐 게임입니다. - 목표 모든 금고를 열고 약탈한 다음 (해당 전리품을 가지고) 꼭대기 층의 계단을 통해 탈출하세요. 플레이어가 게임에서 승리하려면 습격 팀의 모든 구성원이 지붕으로 올라와야 합니다. 남은 스텔스 토큰이 하나도 남지 않은 채 경비원에게 잡히면 플레이...
wikitext
text/x-wiki
- 플레이 방법
버글 브라더스는 타일 탐색과 문제 해결 기능을 갖춘 협동 로그라이크 퍼즐 게임입니다.
- 목표
모든 금고를 열고 약탈한 다음 (해당 전리품을 가지고) 꼭대기 층의 계단을 통해 탈출하세요.
플레이어가 게임에서 승리하려면 습격 팀의 모든 구성원이 지붕으로 올라와야 합니다.
남은 스텔스 토큰이 하나도 남지 않은 채 경비원에게 잡히면 플레이어는 게임에서 패배하게 됩니다.
- 당신의 턴
최대 4개의 액션을 수행하면 같은 층에 있는 경비원이 이동합니다
자신의 차례를 종료할 때 자신의 차례에 사용하지 않은 행동이 두 개 이상 남아 있으면 이벤트가 발생합니다.
순서에 관계없이 액션을 수행할 수 있으며 가능하면 한 차례에 동일한 액션을 여러 번 수행할 수 있습니다.
- 액션
엿보기 : 인접한 방 타일을 공개합니다.
이동 : 인접한 방 타일로 이동하고, 공개되지 않은 경우 공개합니다.
타일별 작업 : 컴퓨터 해킹 또는 금고에 주사위 추가(2개 작업 비용) 또는 금고 해제
캐릭터 능력 : 캐릭터에 따라 캐릭터 고유의 능력은 턴의 첫 번째 액션으로만 사용할 수 있으며 무료이거나 하나 이상의 액션을 소비할 수 있습니다.
도구 사용(무료) : 도구 카드를 폐기하고 그 효과를 적용합니다.
교환(무료) : 같은 타일에 있는 플레이어는 도구와 전리품을 주고 받을 수 있습니다(플레이어의 허락을 받아).
- 금고 해제
안전한 타일을 찾았으면 금고와 같은 행과 같은 열에 있는 타일이 모두 공개되었는지 확인해야 합니다.
예를 들어 금고가 A1에 있는 경우 A열의 모든 타일(A2, A3, A4)과 행1의 모든 타일(B1, C1, D1)이 공개되어야 합니다.(4x4 격자일 경우)
당신의 차례 동안 당신은 2개의 행동을 위해 금고에 주사위를 추가할 수 있습니다.
주어진 금고 타일에는 6개 이상의 주사위를 추가할 수 없습니다.
금고를 위해 공개해야 하는 모든 타일이 공개되면 금고 사각형에서 주사위를 굴려 금고를 "해제"할 수 있습니다.
금고의 조합은 금고와 같은 행과 열에 있는 타일의 오른쪽 하단에 있는 작은 숫자입니다.
예를 들어, 방 타일의 오른쪽 하단에 있는 숫자가 1, 3, 1, 4, 6, 3이라면 1, 3, 4, 6이 나올 때까지 주사위를 굴려야 합니다.
3이 그려진 타일들을 모두 잠금 해제하기 위해 3을 여러 번 굴릴 필요가 없습니다.
굴린 숫자와 일치하는 방 타일에 작은 초록색 원 토큰이 나타납니다.
필요한 모든 숫자가 굴리면 금고가 열리고 도구와 전리품 카드가 주어집니다.
- 시나리오
기본 시나리오는 은행털이, 초보 시나리오는 사무실털이이며, 포트녹스털이는 레이아웃이 더 큽니다.
은행털이 : 건물은 3층으로 4x4 룸 타일 그리드로 배치되어 층당 16개의 타일이 있습니다. 각 층당 1개의 금고와 1개의 계단이 있습니다. 타일 분배에 나열된 모든 타일은 건물에 있을 것입니다.
사무실털이 : 이 시나리오는 초보자에게 좋습니다. 건물은 2층이고 1층당 16개의 타일이 있습니다. 1층당 금고 1개와 계단 1개가 있어서 건물에는 총 금고 2개와 계단 2개가 있습니다. 사무직에는 타일 분포가 다릅니다. 카메라 타일 3개, 지문 타일 2개, 레이저 타일 2개, 모션 타일 2개, 써모 타일 2개, 데드볼트 타일 2개, 키패드 타일 2개, 포이어 타일 2개, 비밀문 타일 2개, 서비스 덕트 타일 2개, 실험실 타일 1개, 화장실 타일 1개, 산책로 타일 2개, 컴퓨터 타일 3개가 있습니다.
포트녹스털이 : 이 시나리오에서 건물은 2층이고 5x5 배치를 가지고 있습니다. 각 층에는 24개의 타일과 빈 공간(벽으로 둘러싸인 회색 정사각형 - 그것을 기둥으로 간주)이 있을 것입니다. 두 층 모두 최소한 하나의 계단이 있을 것이고 나머지 한 쌍은 바닥에 무작위로 분배될 것입니다.
- 타일 분포
은행털이와 포트녹스털이는 아래와 같은 타일 분포를 가질 것입니다. 사무실털이는 위 설명을 참조하십시오.
1 - 화장실
2 - 아트리움, 로비, 비밀 문, 서비스 덕트, 연구실
3 - 컴퓨터, 데드볼트, 감지기, 지문, 키패드, 레이저, 모션, 금고, 계단, 온도, 통로
4 - 카메라
- 룸 타일
아트리움 - 아트리움 타일 위에 있는 동안 이 위치 바로 위나 아래에 있는 타일을 볼 수 있습니다. 그러나 가드가 바로 위나 아래에 있는 타일로 이동하면 사용 가능한 스텔스 토큰을 잃게 됩니다.
카메라 - 플레이어가 이 타일에 들어갈 때 어느 층의 카메라에 가드가 있으면 그 타일에 알람이 발생합니다.
컴퓨터 - 해킹 액션을 사용하려면 컴퓨터실에 있어야 합니다(해당 유형의 해킹 토큰을 생성하려면). 해킹 토큰은 어느 층에서든 해당 알람을 취소하는 데 사용할 수 있습니다. 컴퓨터실에는 지문, 레이저, 모션 등 3가지 유형이 있으며, 이는 취소할 수 있는 3가지 유형의 알람에 해당합니다. 하나는 컴퓨터실당 6개의 토큰만 저장할 수 있습니다.
데드볼트 - 이 타일 유형을 입력하려면 가드나 플레이어가 이미 있지 않는 3개의 액션이 필요합니다. 필요한 3개의 액션없이 공개되지 않은 데드볼트 타일로 이동하려고 하면 타일이 노출되지만 이동하지 않고 나머지 모든 작업이 소모됩니다.
경보기 - 전리품이나 도구를 들고 이 타일로 이동하면 그 타일에 경보가 울립니다.
알람 - 이 타일을 입력하면 해당 타일에 알람이 설정됩니다.
현관 - 경비원은 타일 자체뿐만 아니라 같은 층에 있는 인접한 타일에서도 스파이 활동을 할 수 있습니다.
키패드 - 타일이 잠겨있는 동안 이 타일로 이동하려고 할 때, 이 타일을 사용해 본 횟수와 동일한 횟수의 주사위를 굴립니다(이 순서 포함). 그 중 하나가 6인 경우, 이 타일의 잠금이 해제되어 사용자가 이 타일을 입력하면 작업이 낭비됩니다.
실험실 - 이 타일을 처음 입력한 플레이어가 도구를 그립니다.
화장실 - 공개된 3개의 스텔스 토큰이 이 타일에 배치됩니다. 이 타일에 있을 때 가드가 들어가면 타일의 스텔스 토큰이 자신의 것 대신 제거됩니다. 가드가 들어갈 때 두 명 이상이 화장실 타일에 있으면 많은 스텔스 토큰이 타일에서 제거됩니다. 일단 타일에서 스텔스 토큰이 소진되면 정상적으로 스텔스 토큰을 잃게 됩니다.
레이저(알람) - 이 타일을 입력할 때 2개의 작업을 사용해야 하며 그렇지 않으면 경고가 트리거됩니다.
Motion(알람) - 플레이어가 이 타일을 켜지 않고 들어가면 알람이 발생합니다.
금고 - 금고에 주사위를 넣거나 금고를 깨려면 금고에 있어야 합니다. 금고는 주사위가 없는 것으로 시작해서 최대 6개의 주사위가 나올 수 있습니다.
비밀문 - 벽을 통해 이 타일에 들어갈 수 있습니다(반대로 들어갈 수는 없습니다).
서비스 덕트 - 두 개의 서비스 덕트가 모두 발견되면 다른 층에 있더라도 한 층에서 다른 층으로 이동할 수 있습니다.
계단 - 가장 높은 층이 아닌 한 위층에 있는 상응하는 타일에 아래층 토큰을 붙입니다. 계단에서 상응하는 아래층 타일로 이동하고 훔쳐볼 수 있으며, 타일에서 계단으로 이동할 수 있습니다. 가장 높은 층에 있는 계단은 모든 뿌리가 발견된 후 지붕으로 탈출하는 데 사용됩니다.
Thermo(알람) - 이 타일을 켜면 알람이 발생합니다.
보행로 - 만약 여러분이 이 타일이 드러나지 않은 상태에서 들어가면, 가장 낮은 층이 아닌 한, 그 아래 바닥에 있는 해당 타일로 떨어집니다. 떨어지는 것은 진입한 것으로 간주되지 않습니다. 보행로 타일 위에 있는 동안 여러분은 드러나지 않은 상태에서 아래 타일을 내려다 볼 수 있습니다.
- 경비원
가드의 목적지와 거리는 가드 다이(die)로 표시됩니다. 목적지는 패트롤 데크에서 뽑은 맨 위의 카드에 의해 결정되며 가드는 항상 가장 짧은 경로를 사용합니다. 두 경로가 같은 거리이면 가장 시계 방향의 경로를 사용합니다. 동일한 횟수의 이동으로 여러 경로를 취할 수 있는 경우 가드는 분기점에서 가장 왼쪽 경로를 선택하는 것을 선호합니다. 트리거된 알람에 따라 타일 하나를 추가로 이동합니다. 일단 목적지에 도달하면 새로운 목적지가 설정되고 사용되지 않은 움직임이 남아 있으면 즉시 이동합니다. 트리거된 알람은 목적지를 변경합니다. 금고에 금이 간 후 현재 층의 각 가드와 현재 층 아래의 각 가드는 금고에 금이 간 것을 인식하므로 이동 속도가 영구적으로 1 증가합니다.
순찰갑판이 동나고 재편성될 때마다 그 층에 있는 경비원의 이동 속도는 최대 6개로 영구적으로 1개씩 증가합니다.
- 캐릭터
모든 캐릭터는 기본 능력과 고급 능력을 가지고 있으며, 테이블 설정에 따라 캐릭터가 게임에 가질 능력을 선택할 수 있습니다.
아크로바트 (은퇴자)
유연성(기본 능력): 자유 행동(턴당 여러 번)으로 가드가 있는 타일로 이동할 수 있으며 가드가 이동하기 전에 타일을 떠나면 스텔스 토큰을 잃지 않습니다(스텔스를 잃지 않기 위해 턴을 종료하기 전에 가드와 함께 타일을 떠나는 것을 의미함).
상승 창(고급 능력): 주변 타일(또는 Fort Knox의 빈 타일 옆)에 있는 경우 해당 타일로 한 층 위 또는 아래로 이동하기 위해 3개의 액션을 사용할 수 있지만 타일을 진입하기 위한 모든 이동 규칙은 여전히 적용되므로 모든 액션이 소모됩니다.
해커 (컴퓨터 가이)
방해꾼(기본 능력): 지문, 레이저, 모션 타일을 트리거하지 않으며, 다른 플레이어는 해당 타일을 트리거하지 않습니다. 이 능력은 선택 사항이 아니며 디텍터 및 서모 타일에는 적용되지 않습니다.
노트북 (고급 능력): 자신에게 액션으로 핵 토큰을 추가할 수 있습니다. 이 토큰은 모든 플레이어가 지문, 레이저 또는 모션 핵 토큰으로 사용할 수 있습니다. 자신에게 최대 1개의 핵 토큰만 저장할 수 있습니다.
더 호크 (레콘 프로)
X-Ray (기본 능력): 자유 행동으로, 한 턴에 한 번씩, 인접한 벽을 통해 타일을 드러낼 수 있습니다.
향상(고급 능력): 자유 행동으로, 한 턴에 한 번씩, 최대 두 칸 떨어진 타일을 볼 수 있습니다. 드러나지 않은 타일을 건너뛸 수 없고 벽을 통해 볼 수는 없지만 구석을 엿보고 계단을 올라가는 기능을 사용할 수 있습니다.
착즙기(전자 전문가)
Crybaby (기본 능력): 자유 행동(회전당 여러 번)으로 인접한 타일에 알람을 만들 수 있지만 벽을 통해서는 알람을 만들 수 없습니다.
경로 변경(고급 기능): 자유 조치로, 한 턴에 한 번씩 타일에서 활성 알람을 선택하고 새 순찰 카드를 그리거나 알람 토큰 중 하나를 폐기하여 알람을 트리거할 수 있습니다.
피터맨 (세이프크래커)
안정적인 손(기본 능력): 금고나 키패드를 위해 굴릴 때 1개의 추가 다이를 굴립니다.
드릴(고급 능력): 주사위를 추가하고 타일 위나 아래에 있는 금고를 굴릴 수 있습니다. 그러나 다른 층에서 금고를 약탈할 수 없으므로 약탈물은 회수될 때까지 금고에 남아 있습니다. 게임을 종료하고 이기려면 모든 약탈물을 지붕으로 운반해야 합니다.
레이븐 (매버릭 팰컨)
주의 분산 (기본 능력): 자유 행동으로, 당신은 캐릭터로부터 최대 2개의 타일을 떨어져 있지만 벽을 통해서는 안 됩니다. 당신이 까마귀를 다시 옮길 때까지 까마귀는 그 위치에 남아 있습니다. 그가 까마귀의 타일에 들어갈 때마다 경비원은 한 동작을 잃습니다 (따라서 그 타일에 놓인 까마귀는 그 타일로 들어갈 때까지 경비원에게 영향을 미치지 않습니다)
방해(고급 능력): 자유 행동으로 현재 타일에 까마귀를 배치할 수 있습니다. 만약 경비원이 까마귀와 같은 타일에서 움직임을 시작하고 경보가 울리지 않으면, 그는 모든 움직임을 잃고 까마귀는 당신에게 돌아옵니다.
리거 (팅커 사반트)
해결책 (기본 능력): 다이너마이트 도구부터 시작합니다. 어떤 플레이어가 도구를 발견하면, 그들은 두 개의 도구를 그리고 하나는 유지하고 다른 하나는 버릴 수 있습니다.
팅커 (고급 능력): 도구를 그리기 위해 한 가지 비밀을 잃을 수 있습니다. 어떤 플레이어가 도구를 발견했을 때, 그들은 두 개의 도구를 그리고 하나는 유지하고 다른 하나는 버릴 수 있습니다.
더 룩 (마스터마인드)
주문(기본 능력): 한 턴에 한 번씩 다른 플레이어를 한 타일씩 이동시킬 수 있습니다. 다른 플레이어를 이동시킬 때 레이저와 데드볼트는 추가적인 동작 비용이 들지 않지만 키패드와 알람 타일과 같은 모든 정상적인 이동 규칙이 적용됩니다.
위장(고급 능력): 플레이어와 장소를 교환하는 첫 번째 액션을 사용할 수 있습니다. 이것은 두 사람 모두에게 타일을 입력하는 것으로 간주되지 않습니다. 위장 액션은 첫 번째 액션으로만 사용할 수 있으며, 먼저 실행된 도구 사용과 같은 다른 액션은 무료이지만 위장 액션을 사용할 수 있는 기회를 사용할 수 있습니다.
스포터 (사이키치 곤 로그)
클레어보이언스 (기본 능력): 한 바퀴에 한 번씩, 여러분은 여러분의 바닥을 위한 순찰 갑판의 맨 위 카드를 볼 수 있습니다. 그런 다음 그것을 갑판의 맨 위 또는 맨 아래에 놓도록 선택하세요.
사전 인지 (고급 능력): 한 번씩, 여러분은 이벤트 덱의 맨 위 카드를 볼 수 있습니다. 그런 다음 덱의 맨 위 또는 맨 아래에 배치하도록 선택하십시오.
- 이벤트
차례대로 2개 이하의 동작을 사용하면 이벤트 카드를 뽑지만, 단순히 이벤트를 피하기 위해 타일 사이를 왔다 갔다 할 수는 없습니다. 어떤 이벤트는 가드에게 이익이 되고, 다른 이벤트는 플레이어에게 이익이 됩니다. 그러나 대부분의 이벤트는 게임의 상황에 따라 다르며 적절한 상황에서 팀을 돕거나 방해할 수 있습니다.
브라운 아웃 - 모든 층의 알람 토큰이 제거됩니다. 이렇게 제거된 알람마다 새 순찰 카드가 추첨됩니다.
버디 시스템 - 캐릭터를 선택하고 그들의 미플을 현재 타일로 이동합니다.
계획 변경 - 바닥에 활성 알람이 없으면 바닥의 경비원이 새 순찰 카드를 받습니다.
충돌! - 바닥에 활성 경보가 없으면 가드의 새 목적지는 현재 사용 중인 타일입니다.
백일몽 - 바닥의 가드가 이번에는 움직임이 하나 줄어듭니다.
데드 드롭 - 현재 플레이어가 모든 도구와 전리품을 오른쪽에 있는 플레이어에게 전달합니다.
에스프레소 - 바닥에 있는 가드가 이번에 한 번 더 움직임이 있습니다.
화물용 엘리베이터 - 한 층 위로 떨어집니다. 이것은 탈출 방법으로 사용할 수 없습니다.
내장으로 이동 - 공개되지 않은 타일에 인접한 경우 지금 이동하고, 공개되지 않은 타일이 둘 이상 있는 경우 선택합니다.
체조 - 다음 차례까지 모든 선수들은 마치 계단처럼 현재 타일 위에 있는 보행로 타일 위를 걸을 수 있습니다.
경고! - 다음 플레이어는 차례에 추가 액션을 얻습니다.
총을 뛰어넘는다 - 다음 플레이어의 차례(가드 동작 포함)를 건너뜁니다.
쥬리-리그 - 공구를 획득합니다.
키코드 변경 - 열린 키패드 타일이 다시 잠깁니다.
전등갓 - 스텔스 토큰을 획득합니다.
접지력 상실 - 한 층 아래로 떨어집니다.
Peekhole - 벽이나 위/아래 바닥을 통해서도 인접한 타일 하나를 볼 수 있습니다(이 이벤트를 무시하도록 선택할 수 있습니다).
재부팅 - 공개된 모든 컴퓨터실이 하나의 해킹 토큰으로 재설정됩니다.
시프트 체인지 - 가드가 당신의 층에서 움직이지 않고 대신 다른 층의 가드가 이 턴을 움직인다고 밝혔습니다.
Shoplifting - 도구를 가져간 모든 실험실 타일에서 알람이 트리거됩니다.
찍찍 - 바닥에 있는 가드가 가장 가까운 캐릭터를 향해 타일 하나를 움직입니다.
스위치 표지판 - 바닥의 가드와 그의 목적지가 위치를 바꿉니다.
음성 던지기 - 보호 대상을 현재 위치에서 인접한 타일로 이동합니다(일반적인 이동 규칙에 따라).
타임락 - 플레이어는 한 라운드 동안 계단을 통해 위나 아래로 이동할 수 없습니다.
비디오 루프 - 한 라운드 동안 모든 카메라 타일이 비활성화됩니다.
그는 어디에 있나요? - 당신 층의 경비원이 그의 현재 목적지로 뛰어갑니다.
- 전리품
금고를 열면 전리품을 얻습니다. 벌칙이 함께 제공되어 떨어뜨릴 수 없지만 두 플레이어가 모두 동의하면 자유 액션으로 같은 타일에 있는 다른 플레이어에게 줄 수 있습니다. 플레이어가 지붕으로 탈출하려면 모든 전리품을 보유해야 합니다.
흉상 - 공구 카드는 사용할 수 없지만, 여전히 소지할 수 있습니다.
치와와 - 차례가 시작될 때, 주사위를 굴리세요. 결과가 6이면, 개가 짖고 타일에 알람이 울립니다.
저주받은 잔-그렸을 때 그린 플레이어는 하나의 스텔스가 없으면 하나의 스텔스를 잃게 됩니다.
젬스톤 - 다른 플레이어와 함께 타일로 이동하려면 추가 액션을 사용해야 합니다.
금괴 - 타일 위에 여분의 금괴가 놓여 있습니다. 둘 다 이기려면 뽑아야 합니다. 한 선수는 최대 1개의 금괴를 보유할 수 있습니다.
동위원소 - 열전대 안으로 이동하면 즉시 알람을 트리거합니다.
키카드 - 키카드를 소지한 플레이어가 없는 경우 금고에 금이 갈 수 없습니다.
거울 - 한 바퀴 돌 때마다 한 번의 조치를 덜 취하지만 이제는 해킹이나 경보를 트리거할 필요 없이 레이저 타일을 통과할 수 있습니다.
그림 - 비밀문이나 서비스 덕트는 사용할 수 없습니다. 여전히 정상적으로 출입할 수 있습니다.
페르시안 키티 - 순서를 시작할 때 타일에 없으면 주사위를 굴리세요. 결과가 1 또는 2이면 가장 가까운 경보 타일에 1 타일을 더 가깝게 피신합니다. 키티가 타일에 있는 동안 아무도 그것을 가지고 있지 않으므로 플레이어는 그것을 집어 들고 카드를 얻을 수 있습니다. 키티가 타일에 있으면 아무도 탈출할 수 없습니다.
스탬프 - 순서에 따라 2개가 아닌 3개 이하의 액션을 사용하면 이벤트 카드를 추첨합니다.
티아라 - 경비원과 인접한 타일로 이동하면 경비원이 당신을 볼 것입니다.
- 도구들
금고를 부수거나 실험실에 처음 들어가거나 특정 이벤트 카드를 뽑거나 고급 리거의 특별한 능력을 사용하면 도구를 얻을 수 있습니다. 도구를 버리고 그 효과를 적용하면 차례에 자유 행동으로 도구를 사용할 수 있습니다. 두 플레이어가 모두 동의하면 자유 행동으로 다른 플레이어에게 줄 수 있지만 떨어뜨릴 수는 없습니다.
청사진 - 어느 층에서나 타일을 들여다 볼 수 있습니다.
쇠지레 - 인접한 타일을 영구적으로 비활성화합니다. 이동을 차단하거나 경보를 차단합니다.
크리스탈 볼 - 상위 3개의 이벤트를 그린 후 순서에 상관없이 다시 배치합니다.
도넛 - 보호자를 선택하세요. 다음 번에 움직일 때는 그 대신 움직이지 않습니다.
다이너마이트 - 인접한 벽을 파괴합니다. 현재 타일에 알람을 발생시킵니다.
EMP - 트리거된 모든 알람을 제거합니다. 다음 순서가 시작될 때까지 트리거된 모든 알람은 대신 취소됩니다.
인비저블 슈트 - 경비원이나 카메라에 보이지 않고 이번에는 한 번 더 액션을 얻을 수 있습니다.
메이크업 키트 - 타일의 모든 플레이어가 한 번의 스텔스를 얻습니다.
롤러스케이트 - 이번 턴에 두 가지 액션을 추가로 얻을 수 있습니다.
연막탄 - 타일에 스텔스 토큰 3개를 추가합니다. 이 타일의 플레이어가 사용할 수 있습니다.
스테레오스코프 - 금고를 깨면 다이의 결과를 원하는 쪽으로 변경할 수 있습니다.
열폭탄 - 현재 타일은 지금부터 원래 효과에 더해 계단으로도 취급됩니다(이를 사용하여 3층에서 탈출할 수도 있습니다). 현재 타일에 알람을 발생시킵니다.
바이러스 - 드러난 컴퓨터 타일에 총 3개의 해킹 토큰을 배치합니다.
6f23cce42ac7939acaa876501a2b0477f324bca8
Gamehelpdungeonroll
0
180
1599
1236
2024-06-13T02:53:47Z
Raeroloro
9856
dungeonroll 한글 설명 to KOREAN
wikitext
text/x-wiki
목적
경험과 보물을 얻기 위해 3번의 던전 탐험을 완료하세요. 몬스터와 싸우고, 용을 물리치고 레벨업을 시도하세요. 시대의 영웅이 될 수 있을까요?
플레이어의 턴
모험가는 7개의 파티 주사위를 굴려 동료를 결정합니다. 던전 주사위도 레벨 당 하나씩 굴려야 합니다. 던전 주사위는 물리쳐야 할 몬스터, 열어야 할 보물 상자, 마셔야 할 포션 또는 용일 수 있습니다. 클리어한 레벨마다 1 경험치를 획득합니다. 파티 주사위가 상자를 열거나 포션을 마시기 전에 몬스터를 물리쳐야 합니다. 용굴에 용 주사위가 3개 이상 있으면 용을 물리쳐야 합니다.
몬스터 페이즈
레벨에 해당하는 던전 주사위를 몬스터로 굴립니다(최대 10개).
용은 용굴에 따로 두고 다시 굴릴 수 없습니다.
스크롤을 사용해 파티와 던전 주사위를 다시 굴릴 수 있습니다.
몬스터와 싸우려면 파티와 던전 주사위를 플레이 영역으로 이동합니다.
모험가는 동료를 사용해 몬스터와 싸웁니다. 사용된 동료 주사위는 묘지로 이동합니다.
모험가는 영웅의 특수 능력(탐험마다 여러 번 사용 가능)이나 궁극 능력(탐험마다 한 번 사용 가능)을 사용할 수 있습니다.
몬스터를 모두 물리치면 전리품 페이즈로 진행합니다. 모든 몬스터를 물리칠 수 없다면 모험가는 도망가며 경험치는 얻지 못합니다(그러나 얻은 보물 토큰은 유지합니다).
전리품 페이즈
도둑이나 챔피언은 상자를 얼마든지 열 수 있습니다. 다른 동료는 하나의 상자만 열 수 있습니다.
열린 상자마다 보물을 획득합니다. 보물이 없으면 경험치로 대체합니다.
어떤 파티 주사위도 포션을 마실 수 있습니다. 포션은 동료를 부활시키며 모험가는 부활한 동료의 얼굴을 선택해 다음 라운드에 추가할 수 있습니다.
용 페이즈
용굴에 용 주사위가 3개 이상 있으면 용이 모험가를 공격합니다:
용을 물리치려면 3가지 다른 유형의 동료를 사용해야 합니다(스크롤 제외). 참고: 영웅 능력으로 동일한 유형의 동료를 다른 유형으로 사용할 수 있습니다.
용을 물리치지 못하면 모험가는 도망가며 경험치를 얻지 못합니다(그러나 얻은 보물 토큰은 유지합니다).
용을 물리치면 보물 토큰과 1 경험치를 얻습니다.
재편성 페이즈
모험가는 여관에서 은퇴하거나 영광을 추구할 수 있습니다:
은퇴: 막 완료한 레벨에 해당하는 경험치를 획득합니다. 현재 탐험은 끝납니다.
영광을 추구: 남은 파티 주사위와 보물 토큰을 가지고 다음 던전 레벨로 진행합니다. 새로운 레벨에서는 던전 주사위가 1개 추가됩니다(레벨 1은 던전 주사위 1개, 레벨 2는 던전 주사위 2개 등).
레벨 10을 완료하면 던전을 클리어하고 은퇴해야 합니다.
파티 주사위
동료 유형과 특수 능력
모든 동료는 다음을 수행할 수 있습니다:
몬스터 1마리 처치
보물 상자 1개 열기
포션을 얼마든지 마시기
마법사 (파란 마법사 모자 아이콘): 무수히 많은 슬라임을 물리칠 수 있습니다.
성직자 (회색 망치와 후광 아이콘): 무수히 많은 해골을 물리칠 수 있습니다.
전사 (녹색 교차된 칼 아이콘): 무수히 많은 고블린을 물리칠 수 있습니다.
도둑 (보라색 안대 아이콘): 한 몬스터만 물리칠 수 있지만 상자를 얼마든지 열 수 있습니다.
챔피언 (노란색 날개 달린 헬멧 아이콘): 특정 유형의 몬스터를 무수히 많이 물리칠 수 있으며, 상자를 얼마든지 열 수 있습니다.
스크롤 (주황색 아이콘)은 동료가 아닙니다. 몬스터를 물리칠 수 없지만, 몬스터와 파티 주사위를 다시 굴릴 수 있으며, 포션을 얼마든지 마실 수 있습니다. 상자를 열 수 없습니다.
보물
보물 토큰은 상자를 열거나 용을 물리치면 얻습니다. 보물은 모험가가 도망가더라도 미래 탐험을 위해 유지됩니다. 각 보물 토큰은 게임당 한 번만 사용할 수 있으며, 게임당 특정 수량만큼 제공됩니다. 게임에서 모든 보물 토큰이 모이면 상자를 열 때마다 경험치 1점을 대신 얻습니다. 게임 종료 시 사용하지 않은 보물 토큰은 각각 1 경험치로 계산됩니다.
(3) 보팔 소드 (녹색 검 아이콘): 전사 동료로 사용
(3) 부적 (회색 해골 목걸이 아이콘): 성직자 동료로 사용
(3) 권능의 홀 (파란 불타는 눈 아이콘): 마법사 동료로 사용
(3) 도둑 도구 (보라색 단검과 자물쇠 아이콘): 도둑 동료로 사용
(3) 스크롤 (주황색 스크롤 아이콘): 스크롤로 사용
(4) 투명 반지 (주황색 반지 아이콘): 공격하는 용을 회피(모든 용 주사위를 버리고 페이즈 종료), 보물은 얻지 못함
(6) 용 비늘 (노란색 비늘/방패 아이콘): 비늘 한 쌍당 추가 경험치 2점
(3) 엘릭서/포션 (주황색 병 아이콘): 동료로 사용
(4) 용 미끼 (빨간 고기 아이콘): 모든 몬스터를 용으로 변환, 용굴로 이동
(4) 마을 포털 (청록색 원형 마을 아이콘): 도망 대신 사용(몬스터나 용을 물리치지 못했을 때)하여 해당 레벨의 경험치를 획득. 사용하지 않으면 게임 종료 시 2점.
영웅 능력
모든 영웅(히어로 팩 2 제외)은 게임 시작 시 초보 면을 사용하고, 5 경험치를 얻으면 마스터 면으로 뒤집습니다. 각 영웅은 특수 능력(탐험 중 여러 번 사용 가능)과 궁극 능력(탐험 중 한 번 사용 가능)을 가지고 있습니다.
기본 영웅
성전사/성기사: 전사와 성직자를 서로 사용(특수 능력), 전사나 성직자로 사용(초보 궁극), 보물 버리고 모든 몬스터 처치 --- 모든 상자 열고, 모든 포션 마시고, 모든 용 버림(마스터 궁극)
마법사/미혹자: 스크롤을 모든 동료로 사용(특수 능력), 몬스터를 포션으로 변환(초보 궁극) --- 몬스터 2마리 포션으로 변환(마스터 궁극)
반-고블린/족장: 언제든지 상자를 열고 포션 마심(특수 능력), 고블린을 도둑으로 변환(초보 궁극) --- 고블린 2마리 도둑으로 변환(마스터 궁극)
기사/용사냥꾼: 스크롤을 챔피언으로 사용(초보 특수), 용을 물리칠 때 주사위 하나 감소(마스터 특수) --- 모든 몬스터를 용으로 변환(궁극)
용병/지휘관: 파티 구성 시 주사위 다시 굴림(초보 특수), 전사 하나당 몬스터 하나 추가 처치(마스터 특수), 몬스터 2마리 처치(초보 궁극) --- 파티와 던전 주사위 다시 굴림(마스터 궁극)
음유시인/바드: 도둑과 마법사를 서로 사용(초보 특수), 초보와 챔피언이 몬스터 하나 추가 처치(마스터 특수) --- 모든 용 버림(궁극)
주술사/네크로맨서: 성직자와 마법사를 서로 사용(특수 능력), 해골을 전사로 변환(초보 궁극) --- 해골 2마리 전사로 변환(마스터 궁극)
마법검사/전투마법사: 전사와 마법사를 서로 사용(특수 능력), 전사나 마법사로 사용(초보 궁극) --- 용굴의 모든 주사위 버림(마스터 궁극)
히어로 팩 1
연금술사/마법사: 상자를 포션으로 변환(특수 능력), 동료 부활(초보 궁극) --- 동료 2명 부활(마스터 궁극)
고고학자/무덤 도굴꾼: 파티 구성 시 보물 2개 획득 후 6개 보물 버림(특수 능력), 보물 2개 획득 후 1개 버림(마스터 궁극)
드워프/광전사: 주사위 5개로 시작 후 챔피언이 몬스터 2마리 이상 처치 시 다시 굴림(특수 능력), 몬스터 하나당 챔피언 하나 버리고 다시 굴림(초보 궁극) --- 동료 4명 부활, 용 물리치기 전까지 은퇴 불가(마스터 궁극)
레프리콘/작은 마귀: 모든 포션을 상자로 변환, 보물은 버림(특수 능력), 몬스터 하나를 상자로 변환(초보 궁극) --- 몬스터 2마리를 상자로 변환(마스터 궁극)
정찰자/던전 탐험가: 던전 주사위를 레벨 1-3에 할당(특수 능력), 레벨 1 감소 후 즉시 은퇴(초보 궁극) --- 즉시 은퇴(마스터 궁극)
여마법사/드레이크 킨: 용이 3개 이상일 때 모두 버림(특수 능력), 용 하나당 몬스터 하나 버림(초보 궁극) --- 용 하나당 몬스터 유형 하나 버림(마스터 궁극)
추적자/레인저: 고블린 하나를 레벨당 한 번 다시 굴림(특수 능력), 몬스터 하나 버림(초보 궁극) --- 각 유형의 몬스터 하나 버림(마스터 궁극)
바이킹/언데드 바이킹: 주사위 5개 대신 챔피언 5개 선택(초보 특수), 초보 + 모든 해골 포션으로 변환(마스터 특수) --- 모든 용 주사위 버림(궁극)
프로모션
길드 리더/길드 마스터: 파티 구성 시 주사위 8개 사용(특수 능력), 파티 또는 던전 주사위 하나를 원하는 면으로 설정(초보 궁극) --- 파티와 던전 주사위 하나를 원하는 면으로 설정(마스터 궁극)
시간 여행자/타임 레이디: 파티 구성 시 성직자, 전사, 마법사, 도둑, 스크롤, 챔피언 2명으로 시작(특수 능력), 보물 하나 버려 용 물리치기(초보 궁극) --- 보물 하나 또는 스크롤 하나 버려 용 물리치기(마스터 궁극)
히어로 팩 2
알렉산드라, 지식의 수호자: 스크롤을 챔피언으로 사용, 모든 동료를 스크롤로 사용(특수 능력) --- 스크롤 하나 버려 용굴의 모든 용 물리치기(궁극)
아마르-수엔, 고대의 왕: 도둑이 몬스터 하나 추가 처치(특수 능력) --- 몬스터 유형 하나 버리고 버린 몬스터 하나당 보물 하나 획득(궁극)
카산드라, 저주받은 자: 탐험 시작 시마다 지치며 지친 상태에서 모든 동료가 몬스터 하나 추가 처치. 포션 마시면 회복(특수 능력) --- 포션이나 상자 하나 버림(궁극)
로드 이랴비레, 용군주: 주사위 2개를 스크롤로 설정하고 스크롤 하나 버려 몬스터를 용으로 변환, 3가지 유형 직면 시 회복(특수 능력) --- 모든 용을 동료로 변환, 몬스터 하나 물리치기 또는 상자 하나 열기(궁극)
마르페시아, 아마존 여왕: 용을 소환하려면 주사위 4개 필요, 챔피언이 몬스터 하나 물리치거나 상자 하나 열기(특수 능력) --- 묘지의 모든 주사위를 다시 굴려 스크롤은 버리고 나머지는 파티에 추가(궁극)
스조핀, 악명 높은 군주: 동료 하나로 몬스터 2마리 이상 물리치면 회복(특수 능력) --- 던전 주사위 2개 버림(궁극)
투-락, 미노타우르스 족장: 레벨당 몬스터 하나 다시 굴림(특수 능력) --- 모든 몬스터 버림(궁극)
트리스탄, 외로운 용병: 동료 하나로 몬스터 2마리 이상 물리치면 보물 하나 획득, 보물 하나 사용해 회복(특수 능력) --- 던전 주사위 아무거나 다시 굴림(궁극)
게임 종료
각 플레이어가 3번의 탐험을 완료하면 게임이 종료됩니다. 총 경험치가 가장 높은 플레이어가 승리합니다! 동점일 경우 보물 토큰이 가장 적은 동점 플레이어가 승리합니다. 여전히 동점이라면 동점 플레이어는 공동 승리에 기뻐합니다.
솔로 모드에서는 정상적인 규칙으로 3 라운드를 플레이하고 최고 점수를 목표로 합니다. 점수 등급은 다음과 같습니다:
점수 칭호
0-15 용 먹이
16-23 마을 영웅
24-29 경험 많은 탐험가
30-34 챔피언
35+ 시대의 영웅
6ca88c1d1978348a69033da7af842427370ddfed
Gamehelptichu
0
290
1600
2024-06-14T06:29:32Z
Hyeon lake
9862
손에 든 카드를 먼저 내려놓은 플레이어가 라운드의 트릭을 가져가며, 트릭의 점수가 가장 높은 팀이 승리합니다!
wikitext
text/x-wiki
게임 진행
맞은편에 앉은 각 플레이어가 자신의 팀원입니다. 4명이 총 2개의 팀을 구성하게 됩니다.
게임은 56장의 카드로 진행되며, 4가지 모양(옥, 풀, 탑, 별)으로 이루어진 52장의 숫자 카드와 4장의 특수 카드(참새, 개, 봉황, 용)가 있습니다. 일반 트럼프 카드로 게임을 진행하려고 한다면, 52장의 숫자 카드와 4장의 조커 카드(각 조커에 특수 카드의 능력이 분명히 표시되어 있어야 합니다)를 사용해 게임을 진행할 수 있습니다.
각 플레이어는 먼저 8장의 카드를 손에 든 후에 "라지 티츄"를 선언할 것인지 하지 않을 것인지 결정할 수 있습니다. "라지 티츄"를 선언한 플레이어가 그 라운드에서 모든 카드를 제일 먼저 내려놓은 첫 번째 플레이어가 된다면 200점을 받게 됩니다. 만약 자신의 팀원을 포함한 누구라도 자신보다 먼저 모든 카드를 내려놓았다면 이 점수를 받을 수 없습니다. 모든 플레이어가 라지 티츄 선언 여부를 결정하고 나면, 카드 덱에서 6장의 카트를 추가로 가져옵니다. 이때부터는 "라지 티츄"를 선언할 수 없습니다. 14장의 카드를 모두 뽑은 후부터 자신의 첫 번째 카드를 내리기 전까지, 각 플레이어는 언제든지 "스몰 티츄"를 선언할 수 있습니다. "스몰 티츄"를 선언한 플레이어가 그 라운드에서 모든 카드를 제일 먼저 내려놓은 첫 번째 플레이어가 된다면 100점을 받게 됩니다. 만약 자신의 팀원을 포함한 누구라도 자신보다 먼저 모든 카드를 내려놓았다면 이 점수를 받을 수 없습니다. "라지 티츄"와 "스몰 티츄"의 차이점은 선언하는 타이밍, 손에 든 카드 수, 티츄 성공시 받는 점수의 차이입니다.
모든 플레이어는 세 장의 카드를 각각 한 장씩 다른 플레이어에게 주면서 카드를 동시에 교환합니다. 만약 카드를 교환하기 직전에 상대가 "티츄"를 선언할 경우 플레이어는 자신이 주려고 했던 카드를 변경할 수 있습니다.
카드 교환까지 완료했다면 참새 카드를 가진 플레이어가 첫 번째 트릭의 조건을 결정합니다. 티츄에서 사용하는 카드 조합운 일반적으로 포커의 조합을 사용하지만 일부 예외적인 조합도 있습니다. 선 플레이어가 결정한 조건에 따라 다른 플레이어도 같은 조건의 카드를 내려놓아야 하며, 플레이어 3명이 연속으로 차례를 건너뛸 경우 트릭이 완성됩니다.
카드 조합
단일 카드
원 페어
연속되는 숫자들의 페어 카드(예시/ 3,3,4,4)
트리플
풀하우스(트리플+페어)
스트레이트(연속되는 5장 이상의 카드)
폭탄
폭탄은 더 큰 숫자 조합의 폭탄을 제외하면 위에 있는 모든 카드 조합을 이길 수 있는 특별한 조합입니다. 폭탄은 트릭이 진행되고 있다면 자신의 차례가 아니더라도 언제든지 내려놓을 수 있습니다. 트릭이 완성되기 전이라면, 모든 플레이어는 언제든지 더 큰 폭탄 조합을 내려놓을 수 있습니다.
폭탄 조합: 포 카드(같은 숫자 카드 4장), 스트레이트 플러시(모양이 같고 연속되는 숫자로 이루어진 5장 이상의 카드)
특수 카드
참새 카드
참새를 가진 플레이어가 게임의 첫 트릭의 시작 플레이어가 됩니다. 하지만 반드시 첫 트릭에 참새 카드를 낼 필요는 없습니다. 참새 카드는 단일 카드로 사용하거나 스트레이트 조합에서 1로 사용할 수 있습니다.
참새를 가진 플레이어는 참새 카드를 내려놓으면서 소원으로 2부터 A까지의 카드 중 하나를 말합니다. 소원으로 지정된 카드를 트릭에 포함시켜 내려놓은 플레이어가 있다면 소원은 성취됩니다. 소원은 성취될 때까지 유효합니다. 소원으로 지정된 카드가 손에 없거나 직전 플레이어가 낸 트릭의 조합을 이길 수 없어 소원으로 지정된 카드를 내려놓지 못한다면 다른 카드를 내려놓거나 차례를 넘길 수 있습니다. 참새는 0점으로 간주합니다.
개 카드
개 카드는 숫자 값이 지정되어 있지 않습니다. 따라서 개 카드는 조합에 포함시켜 내려놓을 수 없으며, 반드시 단일 카드로만 내려놓아야 합니다. 개 카드는 자신이 트릭의 시작 플레이어일 때 내려놓을 수 있으며, 자신의 팀원에게 트릭의 시작 플레이어를 넘겨줍니다. 만약 자신의 팀원이 손에 든 카드를 모두 내려놓았다면, 팀원의 다음 차례에 있는 플레이어에게 차례가 넘어갑니다. 어떤 방법으로든(심지어 폭탄으로도) 개 카드의 효력을 중지시킬 수 없습니다. 개 카드는 0점으로 간주합니다.
봉황 카드
봉황 카드는 단일 카드로 사용할 경우 이전 플레이어가 낸 숫자보다 0.5 높은 것으로 간주합니다. 트릭의 시작 플레이어가 단일 카드로 봉황 카드를 내려놓았다면 1.5로 간주합니다. 봉황 카드를 조합에 포함시켜 사용할 경우, 와일드 카드로 빈 자리에 끼워 내려놓을 수 있습니다. 이때 봉황 카드는 직전 카드보다 0.5 높은 것이 아니라 2~A중 하나의 값으로 지정되어 사용합니다. 봉황 카드는 폭탄 조합에는 사용할 수 없습니다. 승점을 계산할 때는 봉황 카드를 -25점으로 계산합니다.
용 카드
용 카드는 단일 카드로만 내려놓을 수 있지만 단일 카드 중 가장 강력한 카드입니다. 오직 폭탄으로만 용 카드를 이길 수 있으며, 아무도 폭탄 카드를 내려놓지 못했다면 용 카드를 내려놓은 플레이어가 트릭의 승자가 됩니다. 용 카드로 트릭에서 승리한 플레이어는 트릭으로 얻은 점수를 상대편에게 넘겨 주어야 합니다. 이때 둘 중 누구에게 줄 것인지 선택할 수 있습니다. 만약 용 카드를 폭탄 조합으로 이겼다면 가장 높은 폭탄 조합을 내려놓은 플레이어가 용 카드를 포함한 모든 카드를 가져갑니다. 트릭을 상대편에게 넘겨줄 필요가 없습니다. 또한 개 카드를 용 카드로 이길 수는 없습니다. 용 카드는 승점을 계산할 때 25점으로 간주합니다.
라운드 종료 및 승점 계산
한 팀의 두 팀원이 모두 카드를 내려놓으면 즉시 라운드가 종료됩니다.
각 팀은 "라지 티츄(200점)" 및 "스몰 티츄(100점)" 성공 여부에 따라 점수를 획득합니다. 티츄에 성공했다면 점수를 얻고, 티츄에 실패했다면 점수를 잃게 됩니다.
만약 상대 팀 중 누구라도 카드를 내려 놓기 전에 자신의 팀이 모두 카드를 내려놓았다면, 즉시 라운드가 종료되고 200점을 획득합니다. 이때는 카드에서 얻는 숭점을 계산하지 않습니다.
마지막까지 남은 플레이어는 손에 남은 카드를 상대팀에게 주어 승점으로 계산하고, 자신이 얻은 모든 트릭은 라운드에서 가장 먼저 모든 카드를 내려놓은 플레이어에게 주어 승점으로 계산합니다.
승점은 각자가 얻은 트릭에 있는 카드를 기반으로 계산합니다. K,10은 10점으로 계산하고, 5는 5점으로 계산합니다. 용 카드는 25점으로, 봉황 카드는 -25점으로 계산합니다. 다른 모든 카드는 0점으로 계산합니다.
2fd16fae87ac758bc84f8ca879d83b3d86cb4c2a
1601
1600
2024-06-14T06:33:16Z
Hyeon lake
9862
wikitext
text/x-wiki
== 게임 진행 ==
맞은편에 앉은 각 플레이어가 자신의 팀원입니다. 4명이 총 2개의 팀을 구성하게 됩니다.
게임은 56장의 카드로 진행되며, 4가지 모양(옥, 풀, 탑, 별)으로 이루어진 52장의 숫자 카드와 4장의 특수 카드(참새, 개, 봉황, 용)가 있습니다. 일반 트럼프 카드로 게임을 진행하려고 한다면, 52장의 숫자 카드와 4장의 조커 카드(각 조커에 특수 카드의 능력이 분명히 표시되어 있어야 합니다)를 사용해 게임을 진행할 수 있습니다.
각 플레이어는 먼저 8장의 카드를 손에 든 후에 "라지 티츄"를 선언할 것인지 하지 않을 것인지 결정할 수 있습니다. "라지 티츄"를 선언한 플레이어가 그 라운드에서 모든 카드를 제일 먼저 내려놓은 첫 번째 플레이어가 된다면 200점을 받게 됩니다. 만약 자신의 팀원을 포함한 누구라도 자신보다 먼저 모든 카드를 내려놓았다면 이 점수를 받을 수 없습니다. 모든 플레이어가 라지 티츄 선언 여부를 결정하고 나면, 카드 덱에서 6장의 카트를 추가로 가져옵니다. 이때부터는 "라지 티츄"를 선언할 수 없습니다. 14장의 카드를 모두 뽑은 후부터 자신의 첫 번째 카드를 내리기 전까지, 각 플레이어는 언제든지 "스몰 티츄"를 선언할 수 있습니다. "스몰 티츄"를 선언한 플레이어가 그 라운드에서 모든 카드를 제일 먼저 내려놓은 첫 번째 플레이어가 된다면 100점을 받게 됩니다. 만약 자신의 팀원을 포함한 누구라도 자신보다 먼저 모든 카드를 내려놓았다면 이 점수를 받을 수 없습니다. "라지 티츄"와 "스몰 티츄"의 차이점은 선언하는 타이밍, 손에 든 카드 수, 티츄 성공시 받는 점수의 차이입니다.
모든 플레이어는 세 장의 카드를 각각 한 장씩 다른 플레이어에게 주면서 카드를 동시에 교환합니다. 만약 카드를 교환하기 직전에 상대가 "티츄"를 선언할 경우 플레이어는 자신이 주려고 했던 카드를 변경할 수 있습니다.
카드 교환까지 완료했다면 참새 카드를 가진 플레이어가 첫 번째 트릭의 조건을 결정합니다. 티츄에서 사용하는 카드 조합운 일반적으로 포커의 조합을 사용하지만 일부 예외적인 조합도 있습니다. 선 플레이어가 결정한 조건에 따라 다른 플레이어도 같은 조건의 카드를 내려놓아야 하며, 플레이어 3명이 연속으로 차례를 건너뛸 경우 트릭이 완성됩니다.
=== 카드 조합 ===
단일 카드
원 페어
연속되는 숫자들의 페어 카드(예시/ 3,3,4,4)
트리플
풀하우스(트리플+페어)
스트레이트(연속되는 5장 이상의 카드)
'''폭탄'''
폭탄은 더 큰 숫자 조합의 폭탄을 제외하면 위에 있는 모든 카드 조합을 이길 수 있는 특별한 조합입니다. 폭탄은 트릭이 진행되고 있다면 자신의 차례가 아니더라도 언제든지 내려놓을 수 있습니다. 트릭이 완성되기 전이라면, 모든 플레이어는 언제든지 더 큰 폭탄 조합을 내려놓을 수 있습니다.
폭탄 조합: 포 카드(같은 숫자 카드 4장), 스트레이트 플러시(모양이 같고 연속되는 숫자로 이루어진 5장 이상의 카드)
=== 특수 카드 ===
'''참새 카드'''
참새를 가진 플레이어가 게임의 첫 트릭의 시작 플레이어가 됩니다. 하지만 반드시 첫 트릭에 참새 카드를 낼 필요는 없습니다. 참새 카드는 단일 카드로 사용하거나 스트레이트 조합에서 1로 사용할 수 있습니다.
참새를 가진 플레이어는 참새 카드를 내려놓으면서 소원으로 2부터 A까지의 카드 중 하나를 말합니다. 소원으로 지정된 카드를 트릭에 포함시켜 내려놓은 플레이어가 있다면 소원은 성취됩니다. 소원은 성취될 때까지 유효합니다. 소원으로 지정된 카드가 손에 없거나 직전 플레이어가 낸 트릭의 조합을 이길 수 없어 소원으로 지정된 카드를 내려놓지 못한다면 다른 카드를 내려놓거나 차례를 넘길 수 있습니다. 참새는 0점으로 간주합니다.
'''개 카드'''
개 카드는 숫자 값이 지정되어 있지 않습니다. 따라서 개 카드는 조합에 포함시켜 내려놓을 수 없으며, 반드시 단일 카드로만 내려놓아야 합니다. 개 카드는 자신이 트릭의 시작 플레이어일 때 내려놓을 수 있으며, 자신의 팀원에게 트릭의 시작 플레이어를 넘겨줍니다. 만약 자신의 팀원이 손에 든 카드를 모두 내려놓았다면, 팀원의 다음 차례에 있는 플레이어에게 차례가 넘어갑니다. 어떤 방법으로든(심지어 폭탄으로도) 개 카드의 효력을 중지시킬 수 없습니다. 개 카드는 0점으로 간주합니다.
'''봉황 카드'''
봉황 카드는 단일 카드로 사용할 경우 이전 플레이어가 낸 숫자보다 0.5 높은 것으로 간주합니다. 트릭의 시작 플레이어가 단일 카드로 봉황 카드를 내려놓았다면 1.5로 간주합니다. 봉황 카드를 조합에 포함시켜 사용할 경우, 와일드 카드로 빈 자리에 끼워 내려놓을 수 있습니다. 이때 봉황 카드는 직전 카드보다 0.5 높은 것이 아니라 2~A중 하나의 값으로 지정되어 사용합니다. 봉황 카드는 폭탄 조합에는 사용할 수 없습니다. 승점을 계산할 때는 봉황 카드를 -25점으로 계산합니다.
'''용 카드'''
용 카드는 단일 카드로만 내려놓을 수 있지만 단일 카드 중 가장 강력한 카드입니다. 오직 폭탄으로만 용 카드를 이길 수 있으며, 아무도 폭탄 카드를 내려놓지 못했다면 용 카드를 내려놓은 플레이어가 트릭의 승자가 됩니다. 용 카드로 트릭에서 승리한 플레이어는 트릭으로 얻은 점수를 상대편에게 넘겨 주어야 합니다. 이때 둘 중 누구에게 줄 것인지 선택할 수 있습니다. 만약 용 카드를 폭탄 조합으로 이겼다면 가장 높은 폭탄 조합을 내려놓은 플레이어가 용 카드를 포함한 모든 카드를 가져갑니다. 트릭을 상대편에게 넘겨줄 필요가 없습니다. 또한 개 카드를 용 카드로 이길 수는 없습니다. 용 카드는 승점을 계산할 때 25점으로 간주합니다.
== 라운드 종료 및 승점 계산 ==
한 팀의 두 팀원이 모두 카드를 내려놓으면 즉시 라운드가 종료됩니다.
각 팀은 "라지 티츄(200점)" 및 "스몰 티츄(100점)" 성공 여부에 따라 점수를 획득합니다. 티츄에 성공했다면 점수를 얻고, 티츄에 실패했다면 점수를 잃게 됩니다.
만약 상대 팀 중 누구라도 카드를 내려 놓기 전에 자신의 팀이 모두 카드를 내려놓았다면, 즉시 라운드가 종료되고 200점을 획득합니다. 이때는 카드에서 얻는 숭점을 계산하지 않습니다.
마지막까지 남은 플레이어는 손에 남은 카드를 상대팀에게 주어 승점으로 계산하고, 자신이 얻은 모든 트릭은 라운드에서 가장 먼저 모든 카드를 내려놓은 플레이어에게 주어 승점으로 계산합니다.
승점은 각자가 얻은 트릭에 있는 카드를 기반으로 계산합니다. K,10은 10점으로 계산하고, 5는 5점으로 계산합니다. 용 카드는 25점으로, 봉황 카드는 -25점으로 계산합니다. 다른 모든 카드는 0점으로 계산합니다.
0c647ef3936263da473b9319d4a07f91301620f0
Gamehelptichu
0
290
1602
1601
2024-06-14T06:37:03Z
Hyeon lake
9862
wikitext
text/x-wiki
== 게임 진행 ==
맞은편에 앉은 각 플레이어가 자신의 팀원입니다. 4명이 총 2개의 팀을 구성하게 됩니다.
게임은 56장의 카드로 진행되며, 4가지 모양(옥, 풀, 탑, 별)으로 이루어진 52장의 숫자 카드와 4장의 특수 카드(참새, 개, 봉황, 용)가 있습니다. 일반 트럼프 카드로 게임을 진행하려고 한다면, 52장의 숫자 카드와 4장의 조커 카드(각 조커에 특수 카드의 능력이 분명히 표시되어 있어야 합니다)를 사용해 게임을 진행할 수 있습니다.
각 플레이어는 먼저 8장의 카드를 손에 든 후에 "라지 티츄"를 선언할 것인지 하지 않을 것인지 결정할 수 있습니다. "라지 티츄"를 선언한 플레이어가 그 라운드에서 모든 카드를 제일 먼저 내려놓은 첫 번째 플레이어가 된다면 200점을 받게 됩니다. 만약 자신의 팀원을 포함한 누구라도 자신보다 먼저 모든 카드를 내려놓았다면 이 점수를 받을 수 없습니다. 모든 플레이어가 라지 티츄 선언 여부를 결정하고 나면, 카드 덱에서 6장의 카트를 추가로 가져옵니다. 이때부터는 "라지 티츄"를 선언할 수 없습니다. 14장의 카드를 모두 뽑은 후부터 자신의 첫 번째 카드를 내리기 전까지, 각 플레이어는 언제든지 "스몰 티츄"를 선언할 수 있습니다. "스몰 티츄"를 선언한 플레이어가 그 라운드에서 모든 카드를 제일 먼저 내려놓은 첫 번째 플레이어가 된다면 100점을 받게 됩니다. 만약 자신의 팀원을 포함한 누구라도 자신보다 먼저 모든 카드를 내려놓았다면 이 점수를 받을 수 없습니다. "라지 티츄"와 "스몰 티츄"의 차이점은 선언하는 타이밍, 손에 든 카드 수, 티츄 성공시 받는 점수의 차이입니다.
모든 플레이어는 세 장의 카드를 각각 한 장씩 다른 플레이어에게 주면서 카드를 동시에 교환합니다. 만약 카드를 교환하기 직전에 상대가 "티츄"를 선언할 경우 플레이어는 자신이 주려고 했던 카드를 변경할 수 있습니다.
카드 교환까지 완료했다면 참새 카드를 가진 플레이어가 첫 번째 트릭의 조건을 결정합니다. 티츄에서 사용하는 카드 조합운 일반적으로 포커의 조합을 사용하지만 일부 예외적인 조합도 있습니다. 선 플레이어가 결정한 조건에 따라 다른 플레이어도 같은 조건의 카드를 내려놓아야 하며, 플레이어 3명이 연속으로 차례를 건너뛸 경우 트릭이 완성됩니다.
=== 카드 조합 ===
단일 카드
원 페어
연속되는 숫자들의 페어 카드(예시/ 3,3,4,4)
트리플
풀하우스(트리플+페어)
스트레이트(연속되는 5장 이상의 카드)
==== '''폭탄''' ====
폭탄은 더 큰 숫자 조합의 폭탄을 제외하면 위에 있는 모든 카드 조합을 이길 수 있는 특별한 조합입니다. 폭탄은 트릭이 진행되고 있다면 자신의 차례가 아니더라도 언제든지 내려놓을 수 있습니다. 트릭이 완성되기 전이라면, 모든 플레이어는 언제든지 더 큰 폭탄 조합을 내려놓을 수 있습니다.
폭탄 조합: 포 카드(같은 숫자 카드 4장), 스트레이트 플러시(모양이 같고 연속되는 숫자로 이루어진 5장 이상의 카드)
=== 특수 카드 ===
==== '''참새 카드''' ====
참새를 가진 플레이어가 게임의 첫 트릭의 시작 플레이어가 됩니다. 하지만 반드시 첫 트릭에 참새 카드를 낼 필요는 없습니다. 참새 카드는 단일 카드로 사용하거나 스트레이트 조합에서 1로 사용할 수 있습니다.
참새를 가진 플레이어는 참새 카드를 내려놓으면서 소원으로 2부터 A까지의 카드 중 하나를 말합니다. 소원으로 지정된 카드를 트릭에 포함시켜 내려놓은 플레이어가 있다면 소원은 성취됩니다. 소원은 성취될 때까지 유효합니다. 소원으로 지정된 카드가 손에 없거나 직전 플레이어가 낸 트릭의 조합을 이길 수 없어 소원으로 지정된 카드를 내려놓지 못한다면 다른 카드를 내려놓거나 차례를 넘길 수 있습니다. 참새는 0점으로 간주합니다.
==== '''개 카드''' ====
개 카드는 숫자 값이 지정되어 있지 않습니다. 따라서 개 카드는 조합에 포함시켜 내려놓을 수 없으며, 반드시 단일 카드로만 내려놓아야 합니다. 개 카드는 자신이 트릭의 시작 플레이어일 때 내려놓을 수 있으며, 자신의 팀원에게 트릭의 시작 플레이어를 넘겨줍니다. 만약 자신의 팀원이 손에 든 카드를 모두 내려놓았다면, 팀원의 다음 차례에 있는 플레이어에게 차례가 넘어갑니다. 어떤 방법으로든(심지어 폭탄으로도) 개 카드의 효력을 중지시킬 수 없습니다. 개 카드는 0점으로 간주합니다.
==== '''봉황 카드''' ====
봉황 카드는 단일 카드로 사용할 경우 이전 플레이어가 낸 숫자보다 0.5 높은 것으로 간주합니다. 트릭의 시작 플레이어가 단일 카드로 봉황 카드를 내려놓았다면 1.5로 간주합니다. 봉황 카드를 조합에 포함시켜 사용할 경우, 와일드 카드로 빈 자리에 끼워 내려놓을 수 있습니다. 이때 봉황 카드는 직전 카드보다 0.5 높은 것이 아니라 2~A중 하나의 값으로 지정되어 사용합니다. 봉황 카드는 폭탄 조합에는 사용할 수 없습니다. 승점을 계산할 때는 봉황 카드를 -25점으로 계산합니다.
==== '''용 카드''' ====
용 카드는 단일 카드로만 내려놓을 수 있지만 단일 카드 중 가장 강력한 카드입니다. 오직 폭탄으로만 용 카드를 이길 수 있으며, 아무도 폭탄 카드를 내려놓지 못했다면 용 카드를 내려놓은 플레이어가 트릭의 승자가 됩니다. 용 카드로 트릭에서 승리한 플레이어는 트릭으로 얻은 점수를 상대편에게 넘겨 주어야 합니다. 이때 둘 중 누구에게 줄 것인지 선택할 수 있습니다. 만약 용 카드를 폭탄 조합으로 이겼다면 가장 높은 폭탄 조합을 내려놓은 플레이어가 용 카드를 포함한 모든 카드를 가져갑니다. 트릭을 상대편에게 넘겨줄 필요가 없습니다. 또한 개 카드를 용 카드로 이길 수는 없습니다. 용 카드는 승점을 계산할 때 25점으로 간주합니다.
== 라운드 종료 및 승점 계산 ==
한 팀의 두 팀원이 모두 카드를 내려놓으면 즉시 라운드가 종료됩니다.
각 팀은 "라지 티츄(200점)" 및 "스몰 티츄(100점)" 성공 여부에 따라 점수를 획득합니다. 티츄에 성공했다면 점수를 얻고, 티츄에 실패했다면 점수를 잃게 됩니다.
만약 상대 팀 중 누구라도 카드를 내려 놓기 전에 자신의 팀이 모두 카드를 내려놓았다면, 즉시 라운드가 종료되고 200점을 획득합니다. 이때는 카드에서 얻는 숭점을 계산하지 않습니다.
마지막까지 남은 플레이어는 손에 남은 카드를 상대팀에게 주어 승점으로 계산하고, 자신이 얻은 모든 트릭은 라운드에서 가장 먼저 모든 카드를 내려놓은 플레이어에게 주어 승점으로 계산합니다.
승점은 각자가 얻은 트릭에 있는 카드를 기반으로 계산합니다. K,10은 10점으로 계산하고, 5는 5점으로 계산합니다. 용 카드는 25점으로, 봉황 카드는 -25점으로 계산합니다. 다른 모든 카드는 0점으로 계산합니다.
b5520c5cf43fd2efe77f315ba9ae035025c4dd87
1603
1602
2024-06-14T11:49:20Z
Hyeon lake
9862
wikitext
text/x-wiki
== 게임 진행 ==
맞은편에 앉은 각 플레이어가 자신의 팀원입니다. 4명이 총 2개의 팀을 구성하게 됩니다.
게임은 56장의 카드로 진행되며, 4가지 모양(옥, 풀, 탑, 별)으로 이루어진 52장의 숫자 카드와 4장의 특수 카드(참새, 개, 봉황, 용)가 있습니다. 일반 트럼프 카드로 게임을 진행하려고 한다면, 52장의 숫자 카드와 4장의 조커 카드(각 조커에 특수 카드의 능력이 분명히 표시되어 있어야 합니다)를 사용해 게임을 진행할 수 있습니다.
각 플레이어는 먼저 8장의 카드를 손에 든 후에 "라지 티츄"를 선언할 것인지 하지 않을 것인지 결정할 수 있습니다. "라지 티츄"를 선언한 플레이어가 그 라운드에서 모든 카드를 제일 먼저 내려놓은 첫 번째 플레이어가 된다면 200점을 받게 됩니다. 만약 자신의 팀원을 포함한 누구라도 자신보다 먼저 모든 카드를 내려놓았다면 이 점수를 받을 수 없습니다. 모든 플레이어가 라지 티츄 선언 여부를 결정하고 나면, 카드 덱에서 6장의 카트를 추가로 가져옵니다. 이때부터는 "라지 티츄"를 선언할 수 없습니다. 14장의 카드를 모두 뽑은 후부터 자신의 첫 번째 카드를 내리기 전까지, 각 플레이어는 언제든지 "스몰 티츄"를 선언할 수 있습니다. "스몰 티츄"를 선언한 플레이어가 그 라운드에서 모든 카드를 제일 먼저 내려놓은 첫 번째 플레이어가 된다면 100점을 받게 됩니다. 만약 자신의 팀원을 포함한 누구라도 자신보다 먼저 모든 카드를 내려놓았다면 이 점수를 받을 수 없습니다. "라지 티츄"와 "스몰 티츄"의 차이점은 선언하는 타이밍, 손에 든 카드 수, 티츄 성공시 받는 점수의 차이입니다.
모든 플레이어는 세 장의 카드를 각각 한 장씩 다른 플레이어에게 주면서 카드를 동시에 교환합니다. 만약 카드를 교환하기 직전에 상대가 "티츄"를 선언할 경우 플레이어는 자신이 주려고 했던 카드를 변경할 수 있습니다.
카드 교환까지 완료했다면 참새 카드를 가진 플레이어가 첫 번째 트릭의 조건을 결정합니다. 티츄에서 사용하는 카드 조합운 일반적으로 포커의 조합을 사용하지만 일부 예외적인 조합도 있습니다. 선 플레이어가 결정한 조건에 따라 다른 플레이어도 같은 조건의 카드를 내려놓아야 하며, 플레이어 3명이 연속으로 차례를 건너뛸 경우 트릭이 완성됩니다.
=== 카드 조합 ===
단일 카드
원 페어
연속되는 숫자들의 페어 카드(예시/ 3,3,4,4)
트리플
풀하우스(트리플+페어)
스트레이트(연속되는 5장 이상의 카드)
==== '''폭탄''' ====
폭탄은 더 큰 숫자 조합의 폭탄을 제외하면 위에 있는 모든 카드 조합을 이길 수 있는 특별한 조합입니다. 폭탄은 트릭이 진행되고 있다면 자신의 차례가 아니더라도 언제든지 내려놓을 수 있습니다. 트릭이 완성되기 전이라면, 모든 플레이어는 언제든지 더 큰 폭탄 조합을 내려놓을 수 있습니다.
폭탄 조합: 포 카드(같은 숫자 카드 4장), 스트레이트 플러시(모양이 같고 연속되는 숫자로 이루어진 5장 이상의 카드)
=== 특수 카드 ===
==== '''참새 카드''' ====
참새를 가진 플레이어가 게임의 첫 트릭의 시작 플레이어가 됩니다. 하지만 반드시 첫 트릭에 참새 카드를 낼 필요는 없습니다. 참새 카드는 단일 카드로 사용하거나 스트레이트 조합에서 1로 사용할 수 있습니다.
참새를 가진 플레이어는 참새 카드를 내려놓으면서 소원으로 2부터 A까지의 카드 중 하나를 말합니다. 소원으로 지정된 카드를 트릭에 포함시켜 내려놓은 플레이어가 있다면 소원은 성취됩니다. 소원은 성취될 때까지 유효합니다. 소원으로 지정된 카드가 손에 없거나 직전 플레이어가 낸 트릭의 조합을 이길 수 없어 소원으로 지정된 카드를 내려놓지 못한다면 다른 카드를 내려놓거나 차례를 넘길 수 있습니다. 참새는 0점으로 간주합니다.
==== '''개 카드''' ====
개 카드는 숫자 값이 지정되어 있지 않습니다. 따라서 개 카드는 조합에 포함시켜 내려놓을 수 없으며, 반드시 단일 카드로만 내려놓아야 합니다. 개 카드는 자신이 트릭의 시작 플레이어일 때 내려놓을 수 있으며, 자신의 팀원에게 트릭의 시작 플레이어를 넘겨줍니다. 만약 자신의 팀원이 손에 든 카드를 모두 내려놓았다면, 팀원의 다음 차례에 있는 플레이어에게 차례가 넘어갑니다. 어떤 방법으로든(심지어 폭탄으로도) 개 카드의 효력을 중지시킬 수 없습니다. 개 카드는 0점으로 간주합니다.
==== '''봉황 카드''' ====
봉황 카드는 단일 카드로 사용할 경우 이전 플레이어가 낸 숫자보다 0.5 높은 것으로 간주합니다. 트릭의 시작 플레이어가 단일 카드로 봉황 카드를 내려놓았다면 1.5로 간주합니다. 봉황 카드를 조합에 포함시켜 사용할 경우, 와일드 카드로 빈 자리에 끼워 내려놓을 수 있습니다. 이때 봉황 카드는 직전 카드보다 0.5 높은 것이 아니라 2~A중 하나의 값으로 지정되어 사용합니다. 봉황 카드는 폭탄 조합에는 사용할 수 없습니다. 승점을 계산할 때는 봉황 카드를 -25점으로 계산합니다.
==== '''용 카드''' ====
용 카드는 단일 카드로만 내려놓을 수 있지만 단일 카드 중 가장 강력한 카드입니다. 오직 폭탄으로만 용 카드를 이길 수 있으며, 아무도 폭탄 카드를 내려놓지 못했다면 용 카드를 내려놓은 플레이어가 트릭의 승자가 됩니다. 용 카드로 트릭에서 승리한 플레이어는 트릭으로 얻은 점수를 상대편에게 넘겨 주어야 합니다. 이때 둘 중 누구에게 줄 것인지 선택할 수 있습니다. 만약 용 카드를 폭탄 조합으로 이겼다면 가장 높은 폭탄 조합을 내려놓은 플레이어가 용 카드를 포함한 모든 카드를 가져갑니다. 트릭을 상대편에게 넘겨줄 필요가 없습니다. 또한 개 카드를 용 카드로 이길 수는 없습니다. 용 카드는 승점을 계산할 때 25점으로 간주합니다.
== 라운드 종료 및 승점 계산 ==
한 팀의 두 팀원이 모두 카드를 내려놓으면 즉시 라운드가 종료됩니다.
각 팀은 "라지 티츄(200점)" 및 "스몰 티츄(100점)" 성공 여부에 따라 점수를 획득합니다. 티츄에 성공했다면 점수를 얻고, 티츄에 실패했다면 점수를 잃게 됩니다.
만약 상대 팀 중 누구라도 카드를 내려 놓기 전에 자신의 팀이 모두 카드를 내려놓았다면, 즉시 라운드가 종료되고 200점을 획득합니다. 이때는 카드에서 얻는 승점을 계산하지 않습니다.
마지막까지 남은 플레이어는 손에 남은 카드를 상대팀에게 주어 승점으로 계산하고, 자신이 얻은 모든 트릭은 라운드에서 가장 먼저 모든 카드를 내려놓은 플레이어에게 주어 승점으로 계산합니다.
승점은 각자가 얻은 트릭에 있는 카드를 기반으로 계산합니다. K,10은 10점으로 계산하고, 5는 5점으로 계산합니다. 용 카드는 25점으로, 봉황 카드는 -25점으로 계산합니다. 다른 모든 카드는 0점으로 계산합니다.
97701ccdf7af047527003bd3bafcedd752023303
Gamehelpfaraway
0
291
1604
2024-06-14T12:15:34Z
Hyeon lake
9862
새 문서: 개요 각 플레이어가 8개의 라운드에 걸쳐 얻은 8개의 타일에 적힌 목표를 완성하는 것을 목표로 합니다. 이 8개의 지역 타일은 타일이 놓여진 순서가 아니라 역순으로(즉 오른쪽에서 왼쪽으로) 점수를 획득하게 됩니다! 게임 진행 1. 먼저, 모든 플레이어가 지역 카드를 선택하여 내려놓습니다. 카드 배치는 내려놓은 순서대로 왼쪽에서 오른쪽으로 배치합니다. 2....
wikitext
text/x-wiki
개요
각 플레이어가 8개의 라운드에 걸쳐 얻은 8개의 타일에 적힌 목표를 완성하는 것을 목표로 합니다.
이 8개의 지역 타일은 타일이 놓여진 순서가 아니라 역순으로(즉 오른쪽에서 왼쪽으로) 점수를 획득하게 됩니다!
게임 진행
1. 먼저, 모든 플레이어가 지역 카드를 선택하여 내려놓습니다. 카드 배치는 내려놓은 순서대로 왼쪽에서 오른쪽으로 배치합니다.
2. 각 플레이어는 방금 내려놓은 카드의 왼쪽 상단에 있는 숫자를 확인합니다. 만약 이전에 내려놓은 카드의 숫자보다 방금 내려놓은 카드의 숫자가 더 크다면 플레이어는 성소 카드를 뽑을 수 있습니다. 이때 성소 카드는 (자신이 내려놓은 카드나 성소 왼쪽 상단에 표시된 단서(지도)의 갯수)+1개의 카드를 뽑아서 손에 듭니다.
3. 공급처에서 (플레이어 인원수)+1개의 카드를 펼치고, 방금 내려놓은 카드의 왼쪽 상단 숫자가 가장 낮은 플레이어부터 숫자 순서대로 공급처에서 지역 카드를 선택하여 손으로 가져옵니다. 이때 남는 1장의 카드는 버립니다.
4. 각 플레이어는 손에 든 성소 카드를 선택하여 내려놓습니다. 남은 성소 카드가 있다면 버립니다.
게임 종료
8개의 라운드가 모두 끝나면 게임이 종료됩니다.
점수를 계산하기 위해 모든 카드를 순서 그대로 뒷면이 보이게 뒤집어 놓습니다.
가장 오른쪽 지역 카드를 공개하고 오른쪽 중간에 있는 요구 사항을 충족하는 경우 오른쪽 아래의 점수를 합산하여 점수를 매깁니다. (점수는 고정된 숫자일 수도 있고 카드 오른쪽 상단의 문양이나 카드의 색 등에 따라 달라질 수 있습니다.)
(이 시점에서 점수 계산은 방금 공개한 카드와 성소로만 진행합니다.)
그런 다음 왼쪽 카드를 공개하고 다시 공개된 카드와 성소로 점수를 계산합니다. 이런 방식으로 8개의 지역 카드를 모두 공개해 점수를 계산합니다. 따라서 게임 초반에 배치된 카드일수록 마지막에 뒤집혀지므로 게임 후반에 배치한 카드를 점수화하는데 도움이 되지 읺을 것입니다.
모든 지역의 점수를 계산하고 나면 성소 하단의 조건도 마저 계산합니다. 최종 점수가 더 높은 플레이어가 승리합니다! (동점일 경우 지역 카드 왼쪽 상단의 숫자가 가장 낮은 플레이어가 승리합니다.)
5e7fe149bc3b384d1a57e2388270402d266af075
1605
1604
2024-06-14T12:16:45Z
Hyeon lake
9862
wikitext
text/x-wiki
=== 개요 ===
각 플레이어가 8개의 라운드에 걸쳐 얻은 8개의 타일에 적힌 목표를 완성하는 것을 목표로 합니다.
이 8개의 지역 타일은 타일이 놓여진 순서가 아니라 역순으로(즉 오른쪽에서 왼쪽으로) 점수를 획득하게 됩니다!
=== 게임 진행 ===
1. 먼저, 모든 플레이어가 지역 카드를 선택하여 내려놓습니다. 카드 배치는 내려놓은 순서대로 왼쪽에서 오른쪽으로 배치합니다.
2. 각 플레이어는 방금 내려놓은 카드의 왼쪽 상단에 있는 숫자를 확인합니다. 만약 이전에 내려놓은 카드의 숫자보다 방금 내려놓은 카드의 숫자가 더 크다면 플레이어는 성소 카드를 뽑을 수 있습니다. 이때 성소 카드는 (자신이 내려놓은 카드나 성소 왼쪽 상단에 표시된 단서(지도)의 갯수)+1개의 카드를 뽑아서 손에 듭니다.
3. 공급처에서 (플레이어 인원수)+1개의 카드를 펼치고, 방금 내려놓은 카드의 왼쪽 상단 숫자가 가장 낮은 플레이어부터 숫자 순서대로 공급처에서 지역 카드를 선택하여 손으로 가져옵니다. 이때 남는 1장의 카드는 버립니다.
4. 각 플레이어는 손에 든 성소 카드를 선택하여 내려놓습니다. 남은 성소 카드가 있다면 버립니다.
=== 게임 종료 ===
8개의 라운드가 모두 끝나면 게임이 종료됩니다.
점수를 계산하기 위해 모든 카드를 순서 그대로 뒷면이 보이게 뒤집어 놓습니다.
가장 오른쪽 지역 카드를 공개하고 오른쪽 중간에 있는 요구 사항을 충족하는 경우 오른쪽 아래의 점수를 합산하여 점수를 매깁니다. (점수는 고정된 숫자일 수도 있고 카드 오른쪽 상단의 문양이나 카드의 색 등에 따라 달라질 수 있습니다.)
(이 시점에서 점수 계산은 방금 공개한 카드와 성소로만 진행합니다.)
그런 다음 왼쪽 카드를 공개하고 다시 공개된 카드와 성소로 점수를 계산합니다. 이런 방식으로 8개의 지역 카드를 모두 공개해 점수를 계산합니다. 따라서 게임 초반에 배치된 카드일수록 마지막에 뒤집혀지므로 게임 후반에 배치한 카드를 점수화하는데 도움이 되지 읺을 것입니다.
모든 지역의 점수를 계산하고 나면 성소 하단의 조건도 마저 계산합니다. 최종 점수가 더 높은 플레이어가 승리합니다! (동점일 경우 지역 카드 왼쪽 상단의 숫자가 가장 낮은 플레이어가 승리합니다.)
2c4f5e922e354ce0e9b8dfafe3628fb9b62261f4
Gamehelpsplendor
0
261
1606
1483
2024-06-15T06:32:23Z
Jihyunnnnnn
9865
그린 -> 가져온 (draw 오역)
wikitext
text/x-wiki
각 개발 카드 데크는 개별적으로 셔플된 다음 테이블 중간에 있는 열에 아래에서 위로 순서를 늘립니다(◯; ◯◯; ◯◯◯).
레벨별로 4장의 카드가 공개됩니다.
고귀한 타일은 섞여서 플레이어 플러스 1이 있는 만큼 많이 드러납니다(예: 4인 게임에 타일 5개).
나머지 타일은 게임에서 제거되므로 게임 중에는 사용되지 않습니다.
플레이어 2명: 골드를 제외한 각 보석 색상의 토큰 3개를 제거합니다(각 4개만 남아 있어야 함).
3명으로: 골드를 제외한 각 보석 색상의 토큰 2개를 제거합니다(각 5개만 남아 있어야 함).
게임 플레이
그런 다음 시계 방향으로 재생이 진행됩니다.
플레이어는 다음 네 가지 동작 중 하나만 수행하도록 선택해야 합니다.
• 색깔이 다른 보석 토큰 3개를 가져가세요.
• 같은 색의 보석 토큰 2개를 가져가세요. 이 동작은 플레이어가 가져갈 때 선택한 색의 토큰이 최소 4개 이상 남아 있을 경우에만 가능합니다.
• 개발 카드 1장 예약 후 골드토큰 1장 가져가세요.
• 테이블 중간에서 페이스업 개발 카드 1장 또는 기존에 예약한 카드를 구매합니다.
토큰 선택
플레이어는 자신의 순서가 끝날 때마다 10개 이상의 토큰을 가질 수 없습니다(조커 포함). 만약 이런 일이 발생하면 10개만 남을 때까지 토큰을 반환해야 합니다. 플레이어는 방금 가져온 것의 전부 또는 일부를 반환할 수 있습니다
개발 카드 예약
카드를 예약하려면 플레이어가 테이블 중간에서 얼굴을 위로 향하게 하거나 다른 플레이어에게 카드를 보여주지 않고 세 덱(레벨 ◯; ◯◯; ◯◯◯) 중 하나에서 첫 번째 카드를 꺼내기만 하면 됩니다.
예약된 카드는 소지하고 있기 때문에 폐기할 수 없습니다.
플레이어는 예약된 카드를 세 장 이상 가지고 있지 않을 수 있으며, 카드를 없애는 유일한 방법은 카드를 사는 것입니다.
카드를 예약하는 것도 골드토큰(조커)을 얻을 수 있는 유일한 방법이며, 골드가 남아있지 않으면 카드를 예약할 수 있지만 골드를 받을 수 없습니다.
a76f05f6801799628a6d93377dd65df39ac9d81f
Gamehelpwerewolves
0
292
1607
2024-06-18T15:29:24Z
Moonyo
7890
새 문서: 《밀러즈 할로우의 늑대인간》의 등장인물 각 플레이어는 게임을 시작할 때 비밀 캐릭터 카드가 할당된 마을 사람을 연기합니다. 늑대인간을 제외하고, '비범한 마을 사람들'이라고도 알려진 특별한 힘을 가진 마을 사람들은 여전히 마을과 같은 편입니다. 늑대인간들 - 그들의 목표는 마을의 다른 주민들을 없애는 것입니다. 매일 밤, 그들은 마을 사람들을 물고,...
wikitext
text/x-wiki
《밀러즈 할로우의 늑대인간》의 등장인물
각 플레이어는 게임을 시작할 때 비밀 캐릭터 카드가 할당된 마을 사람을 연기합니다. 늑대인간을 제외하고, '비범한 마을 사람들'이라고도 알려진 특별한 힘을 가진 마을 사람들은 여전히 마을과 같은 편입니다.
늑대인간들 - 그들의 목표는 마을의 다른 주민들을 없애는 것입니다. 매일 밤, 그들은 마을 사람들을 물고, 죽이고, 먹어 치웁니다. 낮 동안, 그들은 마을 사람들로부터 그들의 정체와 사악한 행동을 숨기려고 노력합니다. 그들은 늑대인간을 먹어 치울 수 없습니다.
평범한 마을 사람들 - 특별한 기술은 없습니다. 그들의 유일한 무기는 늑대인간을 식별하기 위해 행동을 분석하는 능력과 그들과 같은 무고한 사람들이 피해를 입는 것을 막기 위한 신념의 강도입니다.
점쟁이 - 매일 밤, 그녀는 선수의 진정한 성격을 봅니다. 그녀는 마을 사람들이 늑대인간에게 발각되지 않고 늑대인간을 정확하게 식별할 수 있도록 도와야 합니다.
마녀 - 늑대인간이 먹어치운 플레이어를 부활시킬 수 있는 치유의 물약과 플레이어를 제거할 수 있는 독약이 있습니다. 각 물약은 게임당 한 번씩 사용할 수 있으며 두 물약 모두 같은 날 밤에 사용할 수 있습니다. 이 캐릭터를 사용하면 0명 또는 2명의 플레이어가 제거될 수 있습니다.
사냥꾼 - 만일 그가 어떤 이유로 죽는다면, 그는 반격할 수 있습니다. 그는 죽어가는 숨으로 한 명의 플레이어를 쏘고 제거합니다.
The Little Girl - 그녀는 매우 호기심이 많고 눈을 뜨고 늑대인간을 염탐할 수 있습니다. 그러나 그렇게 하는 것이 발각되면, 그녀는 겁에 질려 죽게 됩니다. 이 버전에서, 그녀는 작은 위험(늑대를 보는 것의 20%와 잡히는 것의 20%) 또는 큰 위험(늑대를 보는 것의 40%와 잡히는 것의 40%)을 감수할 수 있습니다.
큐피도 - 그는 두 사람을 즉시 사랑에 빠지게 만드는 힘을 가지고 있습니다. 첫날 밤 동안, 그는 두 명의 플레이어를 선택하고 그들은 게임의 나머지 부분에서 사랑에 빠집니다. 만약 연인 중 한 명이 죽으면, 다른 한 명은 즉시 자살합니다. 그들은 심지어 허세로서도, 그들의 연인을 죽이거나 투표하여 린치를 할 수 없습니다.
도둑 - 도둑이 사용되면 일반 마을 사람 카드 두 장이 추가됩니다. 캐릭터를 처리한 후, 두 장의 추가 카드가 엎어집니다. 첫날 밤, 그는 그들 중 한 장과 카드를 교환하고 게임이 끝날 때까지 그 역할을 할 수 있습니다.
보안관 - 그는 과반수의 투표로 선택됩니다. 그 이후로, 그의 투표는 두 배로 계산됩니다. 그가 탈락하면, 그들은 마지막 숨을 죽이고 그들의 후임자를 선택합니다.
'마을 확장'에 등장하는 건축물들
빌리지 익스팬션 팩을 가지고 놀 때, 마을 사람들은 각각 파워가 있는 건물을 배정받습니다. 이 파워들은 모든 플레이어들이 볼 수 있는 파워들이며, 토큰으로 표시됩니다. (플레이어의 사용자 이름 옆에 표시됩니다.)
방랑자들 - 붙박이장으로 표시됩니다. 특별한 권한이 없는 평범한 집이죠. 하지만, '여주인', ' 이발사', '열매니아크', '까마귀'는 독자 분에게 그들의 권한을 행사할 수 없습니다. 또한 그 집에 있는 사람이 살해되었을 때, 법무관은 독자 분에게 특별한 권한이 있는 집을 허락할 수도 있습니다.
농장/농부 - 표시됨
1eea087d625dbb3990dbcc3f6075bb1b06155040
1608
1607
2024-06-18T15:46:14Z
Moonyo
7890
wikitext
text/x-wiki
"밀러의 공동의 늑대들"의 등장인물
각 플레이어는 게임을 시작할 때 비밀 캐릭터 카드가 할당된 마을 사람을 연기합니다. 늑대인간을 제외하고, '비범한 마을 사람들'이라고도 알려진 특별한 힘을 가진 마을 사람들은 여전히 마을과 같은 편입니다.
늑대인간들 - 그들의 목표는 마을의 다른 주민들을 없애는 것입니다. 매일 밤, 그들은 마을 사람들을 물고, 죽이고, 먹어 치웁니다. 낮 동안, 그들은 마을 사람들로부터 그들의 정체와 사악한 행동을 숨기려고 노력합니다. 그들은 늑대인간을 먹어 치울 수 없습니다.
평범한 마을 사람들 - 특별한 기술은 없습니다. 그들의 유일한 무기는 늑대인간을 식별하기 위해 행동을 분석하는 능력과 그들과 같은 무고한 사람들이 피해를 입는 것을 막기 위한 신념의 강도입니다.
점쟁이 - 매일 밤, 그녀는 선수의 진정한 성격을 봅니다. 그녀는 마을 사람들이 늑대인간에게 발각되지 않고 늑대인간을 정확하게 식별할 수 있도록 도와야 합니다.
마녀 - 늑대인간이 먹어치운 플레이어를 부활시킬 수 있는 치유의 물약과 플레이어를 제거할 수 있는 독약이 있습니다. 각 물약은 게임당 한 번씩 사용할 수 있으며 두 물약 모두 같은 날 밤에 사용할 수 있습니다. 이 캐릭터를 사용하면 0명 또는 2명의 플레이어가 제거될 수 있습니다.
사냥꾼 - 만일 그가 어떤 이유로 죽는다면, 그는 반격할 수 있습니다. 그는 죽어가는 숨으로 한 명의 플레이어를 쏘고 제거합니다.
The Little Girl - 그녀는 매우 호기심이 많고 눈을 뜨고 늑대인간을 염탐할 수 있습니다. 그러나 그렇게 하는 것이 발각되면, 그녀는 겁에 질려 죽게 됩니다. 이 버전에서, 그녀는 작은 위험(늑대를 보는 것의 20%와 잡히는 것의 20%) 또는 큰 위험(늑대를 보는 것의 40%와 잡히는 것의 40%)을 감수할 수 있습니다.
큐피도 - 그는 두 사람을 즉시 사랑에 빠지게 만드는 힘을 가지고 있습니다. 첫날 밤 동안, 그는 두 명의 플레이어를 선택하고 그들은 게임의 나머지 부분에서 사랑에 빠집니다. 만약 연인 중 한 명이 죽으면, 다른 한 명은 즉시 자살합니다. 그들은 심지어 허세로서도, 그들의 연인을 죽이거나 투표하여 린치를 할 수 없습니다.
도둑 - 도둑이 사용되면 일반 마을 사람 카드 두 장이 추가됩니다. 캐릭터를 처리한 후, 두 장의 추가 카드가 엎어집니다. 첫날 밤, 그는 그들 중 한 장과 카드를 교환하고 게임이 끝날 때까지 그 역할을 할 수 있습니다.
보안관 - 그는 과반수의 투표로 선택됩니다. 그 이후로, 그의 투표는 두 배로 계산됩니다. 그가 탈락하면, 그들은 마지막 숨을 죽이고 그들의 후임자를 선택합니다.
'마을 확장'에 등장하는 건물들
빌리지 익스팬션 팩을 가지고 놀 때, 마을 사람들은 각각 파워가 있는 건물을 배정받습니다. 이 파워들은 모든 플레이어들이 볼 수 있는 파워들이며, 토큰으로 표시됩니다. (플레이어의 사용자 이름 옆에 표시됩니다.)
방랑자들 - 붙박이장으로 표시됩니다. 특별한 권한이 없는 평범한 집이죠. 하지만, '여주인', ' 이발사', '열매니아크', '까마귀'는 독자 분에게 그들의 권한을 행사할 수 없습니다. 또한 그 집에 있는 사람이 살해되었을 때, 법무관은 독자 분에게 특별한 권한이 있는 집을 허락할 수도 있습니다.
ce0e6d74f1cdf03ffc9eba432276ff4ad56be244
Gamehelptortugasixteensixtyseven
0
293
1609
2024-06-18T15:50:11Z
Moonyo
7890
새 문서: 요약 선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다 이 후, 플레이어는 두 보트에 무작위로 배포됩니다. 설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다 우승팀...
wikitext
text/x-wiki
요약
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 가슴을 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
조건.
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
행동들
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
모든 플레이어:
* View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
투표 카드
어택스, 뮤티니, 그리고 브롤스는 모든 종류의 투표입니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣습니다. 각 투표 유형에 대해, 투표 데크의 맨 위 투표 카드도 추가됩니다.
16c609be03eb59b6a9e758536d3b6acfb7145067
1610
1609
2024-06-18T15:53:11Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 가슴을 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
==모든 플레이어:==
* View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
==투표 카드==
어택스, 뮤티니, 그리고 브롤스는 모든 종류의 투표입니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣습니다. 각 투표 유형에 대해, 투표 데크의 맨 위 투표 카드도 추가됩니다.
59952fe39c90b06c6ad6bf0e22f447ae7b03f03b
1611
1610
2024-06-18T16:02:21Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 가슴을 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
==모든 플레이어:==
* View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
==투표 카드==
어택스, 뮤티니, 그리고 브롤스는 모든 종류의 투표입니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣을 것입니다. 각 투표 유형에 대해, 투표 데크의 맨 위 투표 카드도 추가됩니다. 그런 다음 가운데 있는 모든 카드가 섞이고 공개되며, 투표의 결과가 수행됩니다.
투표가 완료된 후, 모든 진행된 투표 카드를 투표 데크의 맨 아래에 얼굴을 아래로 향하게 섞고 배치합니다. 투표에 참여한 각 플레이어는 투표 데크의 맨 위에서 새로운 투표 카드를 뽑습니다.
==공략==
배의 선장은 그들의 행동으로 공격을 요청할 수 있습니다. 선장이 배 위에 유일한 플레이어라면, 그들은 여전히 공격을 요청할 수 있습니다. 공격하는 선장의 배에 있는 플레이어들만 투표에 참여합니다.
오직 투표 카드의 맨 위 부분만이 공격에서 중요하고 대포, 횃불 또는 물을 포함합니다. 모든 물은 1개의 횃불을 취소합니다. 만약 적어도 1개의 대포가 있고, 적어도 1개의 "성공적인" 횃불이 투표에서 재생되었다면, 선장은 스페인 갤리온에서 보물 1개를 가져가서 그들의 배에 고정시킬 수 있습니다.
스페인 갤리온호가 보물을 잃어버렸다면 선장은 다른 해적선(플라잉 더치맨 또는 졸리 로저)에 보관된 보물 중 하나를 가져가서 다른 선박에 전당포가 없더라도 둘 중 하나에 보관할 수 있습니다.
예: 대포 2개, 횃불 1개, 물 1개를 재생하면 물이 횃불을 취소하고 "성공한" 횃불이 없기 때문에 공격이 실패합니다.
예: 대포 1개, 횃불 2개, 물 1개를 플레이하면 대포가 1개이고 횃불 중 1개만 물에 의해 취소되어 1개의 "성공" 횃불이 남게 되므로 공격이 성공합니다.
예: 2개의 대포와 2개의 횃불을 연주하면 공격이 성공합니다. 하지만 여전히 보물은 1개만 가져갑니다.
브롤
토르투가 주지사는 그들의 행동으로 싸움을 요청할 수 있습니다. 만약 주지사가 토르투가의 유일한 플레이어라면, 그들은 여전히 싸움을 요청할 수 있습니다. 토르투가의 플레이어들만 투표에 참여합니다.
싸움에서는 투표 카드의 가운데 부분만 문제가 되며 영국 국기 또는 프랑스 국기 중 하나를 포함합니다. 드러난 카드 중 다수가 영국 국기라면, 영국 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 다수가 프랑스 국기라면, 프랑스 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 동점이면, 각 지역에 하나의 보물을 배치합니다. 토르투가에 있는 두 가지 보물은 항상 토르투가에 남아 있지만, 나중에 토르투가에 있는 지역 중 하나로 옮겨질 수도 있습니다.
==반란==
퍼스트 메이트(First Mate of Ship)는 반란을 행동으로 촉구할 수 있습니다. 선장을 제외한 해당 선박의 플레이어만 투표에 참여합니다.
반란은 표의 맨 아래 부분만 문제가 되고 해골이나 조타기 둘 중 하나를 포함합니다. 만약 밝혀진 카드 중 다수가 해골을 가지고 있다면, 반란을 일으키는 배의 선장은 토르투가에게 좌초됩니다. 과반수가 조타기를 가지고 있거나 동점을 가지고 있으면 아무 일도 일어나지 않습니다.
망연자실하기
배에 있는 졸개가 토르투가에 좌초되면, 같은 배의 뒤에 있는 졸개들이 빈 졸개 자리를 채우기 위해 위로 올라갑니다. 선장이 좌초되면, 1등 항해사가 선장이 됩니다. 배에 있는 모든 사람이 좌초되면, 그 배에 있는 보물은 같은 보물에 있는 그 배에 남아 있습니다. 그 보물은 게임 후반에 옮겨지지 않는 한 여전히 팀의 총 보물에 포함됩니다. 만약 플레이어가 빈 배에 탑승하면, 그들은 그 배의 선장이 됩니다.
토르투가에 정박해 있다면, 당신의 전당포는 토르투가의 선 뒤쪽에 놓이게 됩니다. 예를 들어, 만약 토르투가가 현재 비어있다면, "선의 뒤쪽"이 주지사의 위치입니다. 다른 예를 들어, 토르투가가 이미 2개의 전당포를 가지고 있다면, "선의 뒤쪽"은 "3" 위치입니다. 토르투가에 있는 동안 당신은 여전히 턴을 얻고 여전히 정상적으로 플레이어 액션을 수행할 수 있습니다.
만약 당신이 이미 토르투가에 있고 당신이 다시 석패를 당한다면, 당신에게 두 가지 일이 발생합니다. 첫째, 당신의 졸개는 토르투가의 줄 뒤쪽으로 이동되고 당신의 뒤에 순위가 매겨졌던 졸개들은 위로 올라갑니다. (만약 당신이 토르투가에 혼자 있다면 당신의 위치는 변하지 않습니다). 둘째, 당신의 투표 카드 중 하나는 다른 플레이어에 의해 무작위로 선택되고 투표 카드 덱의 맨 아래에 보이지 않게 배치됩니다. 당신은 남은 게임 동안 더 적은 수의 투표 카드로 게임을 하게 됩니다. 토르투가에 있는 동안 여러 번 석패를 당하면, 당신은 여러 투표 카드를 잃게 됩니다. 만약 당신이 투표 카드를 모두 잃는다면, 그렇게 할 수 있는 위치에 있다면 당신은 여전히 투표를 요청할 수 있지만 당신은 참여할 수 없을 것입니다.
==노 젓기 보트==
노 젓는 배로 이동하는 것은 한 가지 행동을 취합니다. 따라서 한 가지 행동으로 노 젓는 배로 이동하고 두 번째 행동으로 배나 토르투가로 이동해야 하기 때문에 토르투가에서 배로 또는 배에서 토르투가로 이동하는 데 총 두 가지 행동이 필요합니다. 현재 노 젓는 배에 전당포가 있는 경우 각 노 젓는 배에 한 번에 한 개의 전당포만 가지고 있기 때문에 다른 전당포는 그 노 젓는 배로 이동할 수 없습니다. 만약 여러분의 전당포가 노 젓는 배에 있다면 투표에 참여하지 않습니다. 다른 전당포를 차단하기 위해 노 젓는 배에 "앉아" 다른 행동(예: 카드 보기 및 공개)을 할 수 있습니다. 노 젓는 배에 타고 있다가 좌초된 경우에는 토르투가의 선 뒤쪽으로 전당포를 반납해야 하지만 투표 카드를 잃지는 않습니다.
==게임의 끝과 승리==
이벤트 덱이 다 떨어지고 공개되지 않은 이벤트 카드가 줄에 있는 5장 밖에 남지 않으면, 그 5장의 카드를 섞고 새로운 줄에 놓으세요. 스페인 아르마다 카드는 마지막 5장의 카드 중 하나가 될 것이고 공개된 카드는 더 이상 교체되지 않을 것입니다.
스페인 아르마다가 공개되면 즉시 보물이 가장 많은 팀이 게임에서 승리합니다. 게임이 끝나면 전당포가 어디에 있든 상관없이 팀과 함께 승리할 수 있습니다.
홀수 선수가 나오는 경기는 스페인 아르마다 카드가 공개됐을 때 팀이 비기면 네덜란드 선수가 이깁니다.
짝수 명의 플레이어가 있는 게임에서 스페인 아르마다 카드가 공개되었을 때 팀이 동점이 되면 게임에서 스페인 아르마다 카드를 제거하고 버려지고 공개되지 않은 모든 이벤트 카드를 새로운 이벤트 덱에 섞습니다. 알바트로스, 레터 오브 마르케 또는 보물 지도와 같이 현재 플레이어 앞에 있는 카드를 섞지 마십시오. 연속으로 5개의 새로운 이벤트 카드를 배치하고 중단한 곳에서 계속 플레이하십시오. 주도권을 잡은 첫 번째 팀이 게임에서 이깁니다.
e1047db6fa96284671f65cfa996acc44d4e3a998
1612
1611
2024-06-18T16:24:39Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 가슴을 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
==모든 플레이어:==
* View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
==투표 카드==
어택스, 뮤티니, 그리고 브롤스는 모든 종류의 투표입니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣을 것입니다. 각 투표 유형에 대해, 투표 데크의 맨 위 투표 카드도 추가됩니다. 그런 다음 가운데 있는 모든 카드가 섞이고 공개되며, 투표의 결과가 수행됩니다.
투표가 완료된 후, 모든 진행된 투표 카드를 투표 데크의 맨 아래에 얼굴을 아래로 향하게 섞고 배치합니다. 투표에 참여한 각 플레이어는 투표 데크의 맨 위에서 새로운 투표 카드를 뽑습니다.
==공략==
배의 선장은 그들의 행동으로 공격을 요청할 수 있습니다. 선장이 배 위에 유일한 플레이어라면, 그들은 여전히 공격을 요청할 수 있습니다. 공격하는 선장의 배에 있는 플레이어들만 투표에 참여합니다.
오직 투표 카드의 맨 위 부분만이 공격에서 중요하고 대포, 횃불 또는 물을 포함합니다. 모든 물은 1개의 횃불을 취소합니다. 만약 적어도 1개의 대포가 있고, 적어도 1개의 "성공적인" 횃불이 투표에서 재생되었다면, 선장은 스페인 갤리온에서 보물 1개를 가져가서 그들의 배에 고정시킬 수 있습니다.
스페인 갤리온호가 보물을 잃어버렸다면 선장은 다른 해적선(플라잉 더치맨 또는 졸리 로저)에 보관된 보물 중 하나를 가져가서 다른 선박에 전당포가 없더라도 둘 중 하나에 보관할 수 있습니다.
예: 대포 2개, 횃불 1개, 물 1개를 재생하면 물이 횃불을 취소하고 "성공한" 횃불이 없기 때문에 공격이 실패합니다.
예: 대포 1개, 횃불 2개, 물 1개를 플레이하면 대포가 1개이고 횃불 중 1개만 물에 의해 취소되어 1개의 "성공" 횃불이 남게 되므로 공격이 성공합니다.
예: 2개의 대포와 2개의 횃불을 연주하면 공격이 성공합니다. 하지만 여전히 보물은 1개만 가져갑니다.
브롤
토르투가 주지사는 그들의 행동으로 싸움을 요청할 수 있습니다. 만약 주지사가 토르투가의 유일한 플레이어라면, 그들은 여전히 싸움을 요청할 수 있습니다. 토르투가의 플레이어들만 투표에 참여합니다.
싸움에서는 투표 카드의 가운데 부분만 문제가 되며 영국 국기 또는 프랑스 국기 중 하나를 포함합니다. 드러난 카드 중 다수가 영국 국기라면, 영국 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 다수가 프랑스 국기라면, 프랑스 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 동점이면, 각 지역에 하나의 보물을 배치합니다. 토르투가에 있는 두 가지 보물은 항상 토르투가에 남아 있지만, 나중에 토르투가에 있는 지역 중 하나로 옮겨질 수도 있습니다.
==반란==
퍼스트 메이트(First Mate of Ship)는 반란을 행동으로 촉구할 수 있습니다. 선장을 제외한 해당 선박의 플레이어만 투표에 참여합니다.
반란은 표의 맨 아래 부분만 문제가 되고 해골이나 조타기 둘 중 하나를 포함합니다. 만약 밝혀진 카드 중 다수가 해골을 가지고 있다면, 반란을 일으키는 배의 선장은 토르투가에게 좌초됩니다. 과반수가 조타기를 가지고 있거나 동점을 가지고 있으면 아무 일도 일어나지 않습니다.
망연자실하기
배에 있는 졸개가 토르투가에 좌초되면, 같은 배의 뒤에 있는 졸개들이 빈 졸개 자리를 채우기 위해 위로 올라갑니다. 선장이 좌초되면, 1등 항해사가 선장이 됩니다. 배에 있는 모든 사람이 좌초되면, 그 배에 있는 보물은 같은 보물에 있는 그 배에 남아 있습니다. 그 보물은 게임 후반에 옮겨지지 않는 한 여전히 팀의 총 보물에 포함됩니다. 만약 플레이어가 빈 배에 탑승하면, 그들은 그 배의 선장이 됩니다.
토르투가에 정박해 있다면, 당신의 전당포는 토르투가의 선 뒤쪽에 놓이게 됩니다. 예를 들어, 만약 토르투가가 현재 비어있다면, "선의 뒤쪽"이 주지사의 위치입니다. 다른 예를 들어, 토르투가가 이미 2개의 전당포를 가지고 있다면, "선의 뒤쪽"은 "3" 위치입니다. 토르투가에 있는 동안 당신은 여전히 턴을 얻고 여전히 정상적으로 플레이어 액션을 수행할 수 있습니다.
만약 당신이 이미 토르투가에 있고 당신이 다시 석패를 당한다면, 당신에게 두 가지 일이 발생합니다. 첫째, 당신의 졸개는 토르투가의 줄 뒤쪽으로 이동되고 당신의 뒤에 순위가 매겨졌던 졸개들은 위로 올라갑니다. (만약 당신이 토르투가에 혼자 있다면 당신의 위치는 변하지 않습니다). 둘째, 당신의 투표 카드 중 하나는 다른 플레이어에 의해 무작위로 선택되고 투표 카드 덱의 맨 아래에 보이지 않게 배치됩니다. 당신은 남은 게임 동안 더 적은 수의 투표 카드로 게임을 하게 됩니다. 토르투가에 있는 동안 여러 번 석패를 당하면, 당신은 여러 투표 카드를 잃게 됩니다. 만약 당신이 투표 카드를 모두 잃는다면, 그렇게 할 수 있는 위치에 있다면 당신은 여전히 투표를 요청할 수 있지만 당신은 참여할 수 없을 것입니다.
==노 젓기 보트==
노 젓는 배로 이동하는 것은 한 가지 행동을 취합니다. 따라서 한 가지 행동으로 노 젓는 배로 이동하고 두 번째 행동으로 배나 토르투가로 이동해야 하기 때문에 토르투가에서 배로 또는 배에서 토르투가로 이동하는 데 총 두 가지 행동이 필요합니다. 현재 노 젓는 배에 전당포가 있는 경우 각 노 젓는 배에 한 번에 한 개의 전당포만 가지고 있기 때문에 다른 전당포는 그 노 젓는 배로 이동할 수 없습니다. 만약 여러분의 전당포가 노 젓는 배에 있다면 투표에 참여하지 않습니다. 다른 전당포를 차단하기 위해 노 젓는 배에 "앉아" 다른 행동(예: 카드 보기 및 공개)을 할 수 있습니다. 노 젓는 배에 타고 있다가 좌초된 경우에는 토르투가의 선 뒤쪽으로 전당포를 반납해야 하지만 투표 카드를 잃지는 않습니다.
==게임의 끝과 승리==
이벤트 덱이 다 떨어지고 공개되지 않은 이벤트 카드가 줄에 있는 5장 밖에 남지 않으면, 그 5장의 카드를 섞고 새로운 줄에 놓으세요. 스페인 아르마다 카드는 마지막 5장의 카드 중 하나가 될 것이고 공개된 카드는 더 이상 교체되지 않을 것입니다.
스페인 아르마다가 공개되면 즉시 보물이 가장 많은 팀이 게임에서 승리합니다. 게임이 끝나면 전당포가 어디에 있든 상관없이 팀과 함께 승리할 수 있습니다.
홀수 선수가 나오는 경기는 스페인 아르마다 카드가 공개됐을 때 팀이 비기면 네덜란드 선수가 이깁니다.
짝수 명의 플레이어가 있는 게임에서 스페인 아르마다 카드가 공개되었을 때 팀이 동점이 되면 게임에서 스페인 아르마다 카드를 제거하고 버려지고 공개되지 않은 모든 이벤트 카드를 새로운 이벤트 덱에 섞습니다. 알바트로스, 레터 오브 마르케 또는 보물 지도와 같이 현재 플레이어 앞에 있는 카드를 섞지 마십시오. 연속으로 5개의 새로운 이벤트 카드를 배치하고 중단한 곳에서 계속 플레이하십시오. 주도권을 잡은 첫 번째 팀이 게임에서 이깁니다.
==이벤트 카드==
아래 설명에서 모든 플레이어는 자신을 포함합니다. 다른 플레이어는 자신을 포함하지 않습니다. 모든 카드 해상도는 공개 시 필수입니다.
====유용한 카드(6)====
* 마크의 편지 (3): 드러버는 토르투가나 노 젓는 배에 있는 모든 플레이어를 두 배의 라인 뒤쪽으로 이동시킵니다. 드러버는 또한 이 카드를 저장하고 미래의 행동으로 사용할 수 있습니다.
* 권총 (3): 폭로자가 다른 플레이어를 선택합니다. 그 플레이어는 낙오되었습니다. 권총은 나중의 액션으로 사용하기 위해 저장할 수 없습니다.
====상처를 주는 카드(6)====
* 알바트로스 (3): 폭로자는 게임의 나머지 기간 동안 이 카드를 그들 앞에 얼굴을 비추게 합니다. 만약 어떤 시점에서 배에 총 2개의 알바트로스가 있다면, 그 배에 있는 모든 플레이어는 토르투가에 버려집니다. 예: 게임 초반에 일등 항해사가 알바트로스를 공개하고 그들 앞에 그것을 가지고 있습니다. 만약 그 일등 항해사의 배에 있는 누군가 (자신들을 포함하여) 또 다른 알바트로스를 공개하면, 그 배에 있는 모든 플레이어(심지어 알바트로스 카드가 없는 플레이어도)는 토르투가에 버려집니다. 만약 당신이 알바트로스 카드 2개를 가지고 배에 들어가면, 배에 있는 모든 사람(방금 배에 가입한 당신을 포함하여)은 즉시 토르투가에 버려집니다. 당신은 본질적으로 걷는 폭탄입니다. 알바트로스 카드는 토르투가에 아무런 영향을 미치지 않습니다. 만약 둘 이상의 플레이어가 알바트로스 카드에 빠져 동시에 토르투가에 들어오면, 그들은 순위를 뒤집습니다 (캐빈 보이는 토르투가에서 최고 순위의 오픈 폰 자리를 얻게 되고, 캡틴은 최악이 됩니다 등).
* Black Spot (3): Rebeller가 잠겼습니다.
====TREASURE MAPS (3)====
폭로자는 보물 지도를 다른 플레이어에게 줍니다. 카드가 주어진 플레이어가 보물 지도를 사용할 때, 그것은 액션으로 간주되지 않습니다. 플레이어는 여러 개의 보물 지도를 받고 소유할 수 있습니다. 2인용 및 3인용 게임에서 플레이어는 여전히 드러난 보물 지도를 다른 플레이어에게 주어야 합니다.
* 아틀란티스 (1): 소유자는 플레이어의 차례 직전에 한 배에서 다른 배의 라인 뒤쪽으로 이동할 수 있습니다 (자신의 차례 포함). 아틀란티스를 사용하는 것은 행동으로 간주되지 않습니다. 소유자는 토르투가나 노 젓는 배에서 배로 이동하기 위해 이 카드를 사용할 수 없습니다. 사용 후 폐기하십시오.
* 엘도라도 (1): 소유자는 즉시 투표 카드를 한 장 더 뽑습니다. 앞으로 있을 투표에서, 소유자는 보통 투표 카드 대신 두 장의 투표 카드를 사용할 수 있습니다. 엘도라도 (토투가에서 투표 카드가 잠기는 것을 줄여주는 사람들을 포함하여) 주어진 플레이어는 엘도라도 카드를 가지고 더 많은 투표 카드를 손에 유지하기 위해 그 능력을 사용하지 않을 수 있습니다. 투표에서 두 장의 카드를 사용한 후 엘도라도 카드를 버리세요.
* 젊음의 샘 (1): 소유자는 흑점을 드러내거나 권총으로 총을 맞거나 선장에게 유괴되거나 반란에 성공한 후 유괴되지 않기로 선택할 수 있습니다. 사용 후 폐기하십시오.
====스타드 카드 (각 게임에 무작위로 3개 추가)====
* 검은 가루: 폭로자는 폭발 토큰을 노 젓는 배에 놓습니다. 그 노 젓는 배는 게임의 나머지 부분에 사용되지 않을 수도 있습니다. 만약 플레이어가 현재 그 노 젓는 배에 있다면, 그들은 토르투가의 선 뒤쪽에 정박하게 됩니다. 노 젓는 배 없이 배로 이동하는 유일한 방법은 마르케 또는 아틀란티스의 편지를 사용하는 것입니다.
* 캐빈 피버: 폭로자가 다른 플레이어 1명을 선택합니다. 폭로자와 선택한 플레이어의 충성 카드는 뒤섞여 각각에게 재배포됩니다. 그들은 각각 비밀리에 새로운 충성 카드를 봅니다.
* 까마귀 둥지: 폭로자는 투표 데크에 한 플레이어의 투표 카드 손을 아래로 향하게 배치합니다. 그런 다음 폭로자는 개인적으로 해당 플레이어의 손에 있던 카드를 대체할 전체 투표 데크를 검색합니다. 완료 후 투표 데크를 섞습니다. 까마귀 둥지가 공개되었을 때 가지고 있던 것과 동일한 수의 투표 카드로 해당 플레이어의 손을 교체해야 합니다.
* 여덟 개의 종: 폭로자의 배나 섬에 있는 모든 졸개들은 주머니에 넣어지고 무작위로 그 배나 섬으로 다시 꺼내집니다. 폭로자가 혼자 있거나 노 젓는 배에 있으면 효과가 없습니다.
* 파사드: 폭로자는 오른쪽에 앉은 플레이어와 폰 위치를 바꿉니다.
* 해적 코드: 폭로자는 자신들이 속해 있었을 다음 두 표 (공격, 반란, 또는 싸움)에 참여하지 않을 수 있습니다. 만약 그렇게 할 수 있는 위치에 있다면 그들은 여전히 투표를 요청할 수 있습니다. 만약 그들이 투표를 위해 혼자 있다면, 투표 카드는 여전히 갑판에서 추가됩니다. 두 번째 투표에 참여하지 않은 후 폐기하세요.
* Scurvy: 폭로자를 포함하여 폭로자와 같은 배 또는 섬에 있는 모든 플레이어는 다음 순서를 잃습니다. 그 플레이어는 Scurvy 폭로자의 배 또는 섬에서 이동하더라도 여전히 다음 순서를 잃습니다. 순서를 잃는 플레이어는 스킵되지 않은 플레이어가 요청한 관련 싸움, 뮤티니 또는 공격에 여전히 참여할 수 있습니다. 2인용 게임에서 생략된 플레이어는 다음 순서에 대한 두 가지 동작을 모두 놓칩니다.
* 폭풍의 바다: 폭로자의 배에 있는 모든 보물은 (배에 있는 경우) 스페인 갈레온으로 돌아가거나 (토르투가에 있는 경우) 토르투가 보물은 원래의 시작 지역으로 돌아갑니다. 스페인 갈레온에 보물이 있다면, 갤레온에 있는 보물이 사라질 때까지 선장들은 서로의 배를 공격할 수 없습니다. 만약 폭로자가 보물이 없는 배에 있거나 노 젓는 배에 있다면 아무런 효과가 없습니다.
===게임 엔더 (1)===
* 스페인 아르마다: 스페인 아르마다 카드가 공개되면 게임이 끝납니다. 스페인 아르마다 카드가 마지막으로 남은 카드라면, 플레이어는 카드를 보거나 다른 플레이어에게 카드를 공개하도록 강요하는 동작을 사용하지 않을 수 있습니다.
5e3450d78ea45d02272e6472d6b99a14fb5b4836
1613
1612
2024-06-18T16:47:25Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 가슴을 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
==모든 플레이어:==
* View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
==투표 카드==
어택스, 뮤티니, 그리고 브롤스는 모든 종류의 투표입니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣을 것입니다. 각 투표 유형에 대해, 투표 데크의 맨 위 투표 카드도 추가됩니다. 그런 다음 가운데 있는 모든 카드가 섞이고 공개되며, 투표의 결과가 수행됩니다.
투표가 완료된 후, 모든 진행된 투표 카드를 투표 데크의 맨 아래에 얼굴을 아래로 향하게 섞고 배치합니다. 투표에 참여한 각 플레이어는 투표 데크의 맨 위에서 새로운 투표 카드를 뽑습니다.
==공격==
배의 선장은 그들의 행동으로 공격을 요청할 수 있습니다. 선장이 배 위에 유일한 플레이어라면, 그들은 여전히 공격을 요청할 수 있습니다. 공격하는 선장의 배에 있는 플레이어들만 투표에 참여합니다.
오직 투표 카드의 맨 위 부분만이 공격에서 중요하고 대포, 횃불 또는 물을 포함합니다. 모든 물은 1개의 횃불을 취소합니다. 만약 적어도 1개의 대포가 있고, 적어도 1개의 "성공적인" 횃불이 투표에서 재생되었다면, 선장은 스페인 갤리온에서 보물 1개를 가져가서 그들의 배에 고정시킬 수 있습니다.
스페인 갤리온호가 보물을 잃어버렸다면 선장은 다른 해적선(플라잉 더치맨 또는 졸리 로저)에 보관된 보물 중 하나를 가져가서 다른 선박에 전당포가 없더라도 둘 중 하나에 보관할 수 있습니다.
예: 대포 2개, 횃불 1개, 물 1개를 재생하면 물이 횃불을 취소하고 "성공한" 횃불이 없기 때문에 공격이 실패합니다.
예: 대포 1개, 횃불 2개, 물 1개를 플레이하면 대포가 1개이고 횃불 중 1개만 물에 의해 취소되어 1개의 "성공" 횃불이 남게 되므로 공격이 성공합니다.
예: 2개의 대포와 2개의 횃불을 연주하면 공격이 성공합니다. 하지만 여전히 보물은 1개만 가져갑니다.
브롤
토르투가 주지사는 그들의 행동으로 싸움을 요청할 수 있습니다. 만약 주지사가 토르투가의 유일한 플레이어라면, 그들은 여전히 싸움을 요청할 수 있습니다. 토르투가의 플레이어들만 투표에 참여합니다.
싸움에서는 투표 카드의 가운데 부분만 문제가 되며 영국 국기 또는 프랑스 국기 중 하나를 포함합니다. 드러난 카드 중 다수가 영국 국기라면, 영국 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 다수가 프랑스 국기라면, 프랑스 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 동점이면, 각 지역에 하나의 보물을 배치합니다. 토르투가에 있는 두 가지 보물은 항상 토르투가에 남아 있지만, 나중에 토르투가에 있는 지역 중 하나로 옮겨질 수도 있습니다.
==반란==
퍼스트 메이트(First Mate of Ship)는 반란을 행동으로 촉구할 수 있습니다. 선장을 제외한 해당 선박의 플레이어만 투표에 참여합니다.
반란은 표의 맨 아래 부분만 문제가 되고 해골이나 조타기 둘 중 하나를 포함합니다. 만약 밝혀진 카드 중 다수가 해골을 가지고 있다면, 반란을 일으키는 배의 선장은 토르투가에게 좌초됩니다. 과반수가 조타기를 가지고 있거나 동점을 가지고 있으면 아무 일도 일어나지 않습니다.
망연자실하기
배에 있는 졸개가 토르투가에 좌초되면, 같은 배의 뒤에 있는 졸개들이 빈 졸개 자리를 채우기 위해 위로 올라갑니다. 선장이 좌초되면, 1등 항해사가 선장이 됩니다. 배에 있는 모든 사람이 좌초되면, 그 배에 있는 보물은 같은 보물에 있는 그 배에 남아 있습니다. 그 보물은 게임 후반에 옮겨지지 않는 한 여전히 팀의 총 보물에 포함됩니다. 만약 플레이어가 빈 배에 탑승하면, 그들은 그 배의 선장이 됩니다.
토르투가에 정박해 있다면, 당신의 전당포는 토르투가의 선 뒤쪽에 놓이게 됩니다. 예를 들어, 만약 토르투가가 현재 비어있다면, "선의 뒤쪽"이 주지사의 위치입니다. 다른 예를 들어, 토르투가가 이미 2개의 전당포를 가지고 있다면, "선의 뒤쪽"은 "3" 위치입니다. 토르투가에 있는 동안 당신은 여전히 턴을 얻고 여전히 정상적으로 플레이어 액션을 수행할 수 있습니다.
만약 당신이 이미 토르투가에 있고 당신이 다시 석패를 당한다면, 당신에게 두 가지 일이 발생합니다. 첫째, 당신의 졸개는 토르투가의 줄 뒤쪽으로 이동되고 당신의 뒤에 순위가 매겨졌던 졸개들은 위로 올라갑니다. (만약 당신이 토르투가에 혼자 있다면 당신의 위치는 변하지 않습니다). 둘째, 당신의 투표 카드 중 하나는 다른 플레이어에 의해 무작위로 선택되고 투표 카드 덱의 맨 아래에 보이지 않게 배치됩니다. 당신은 남은 게임 동안 더 적은 수의 투표 카드로 게임을 하게 됩니다. 토르투가에 있는 동안 여러 번 석패를 당하면, 당신은 여러 투표 카드를 잃게 됩니다. 만약 당신이 투표 카드를 모두 잃는다면, 그렇게 할 수 있는 위치에 있다면 당신은 여전히 투표를 요청할 수 있지만 당신은 참여할 수 없을 것입니다.
==노 젓기 보트==
노 젓는 배로 이동하는 것은 한 가지 행동을 취합니다. 따라서 한 가지 행동으로 노 젓는 배로 이동하고 두 번째 행동으로 배나 토르투가로 이동해야 하기 때문에 토르투가에서 배로 또는 배에서 토르투가로 이동하는 데 총 두 가지 행동이 필요합니다. 현재 노 젓는 배에 전당포가 있는 경우 각 노 젓는 배에 한 번에 한 개의 전당포만 가지고 있기 때문에 다른 전당포는 그 노 젓는 배로 이동할 수 없습니다. 만약 여러분의 전당포가 노 젓는 배에 있다면 투표에 참여하지 않습니다. 다른 전당포를 차단하기 위해 노 젓는 배에 "앉아" 다른 행동(예: 카드 보기 및 공개)을 할 수 있습니다. 노 젓는 배에 타고 있다가 좌초된 경우에는 토르투가의 선 뒤쪽으로 전당포를 반납해야 하지만 투표 카드를 잃지는 않습니다.
==게임의 끝과 승리==
이벤트 덱이 다 떨어지고 공개되지 않은 이벤트 카드가 줄에 있는 5장 밖에 남지 않으면, 그 5장의 카드를 섞고 새로운 줄에 놓으세요. 스페인 아르마다 카드는 마지막 5장의 카드 중 하나가 될 것이고 공개된 카드는 더 이상 교체되지 않을 것입니다.
스페인 아르마다가 공개되면 즉시 보물이 가장 많은 팀이 게임에서 승리합니다. 게임이 끝나면 전당포가 어디에 있든 상관없이 팀과 함께 승리할 수 있습니다.
홀수 선수가 나오는 경기는 스페인 아르마다 카드가 공개됐을 때 팀이 비기면 네덜란드 선수가 이깁니다.
짝수 명의 플레이어가 있는 게임에서 스페인 아르마다 카드가 공개되었을 때 팀이 동점이 되면 게임에서 스페인 아르마다 카드를 제거하고 버려지고 공개되지 않은 모든 이벤트 카드를 새로운 이벤트 덱에 섞습니다. 알바트로스, 레터 오브 마르케 또는 보물 지도와 같이 현재 플레이어 앞에 있는 카드를 섞지 마십시오. 연속으로 5개의 새로운 이벤트 카드를 배치하고 중단한 곳에서 계속 플레이하십시오. 주도권을 잡은 첫 번째 팀이 게임에서 이깁니다.
==이벤트 카드==
아래 설명에서 모든 플레이어는 자신을 포함합니다. 다른 플레이어는 자신을 포함하지 않습니다. 모든 카드 해상도는 공개 시 필수입니다.
====유용한 카드(6)====
* 마크의 편지 (3): 드러버는 토르투가나 노 젓는 배에 있는 모든 플레이어를 두 배의 라인 뒤쪽으로 이동시킵니다. 드러버는 또한 이 카드를 저장하고 미래의 행동으로 사용할 수 있습니다.
* 권총 (3): 폭로자가 다른 플레이어를 선택합니다. 그 플레이어는 낙오되었습니다. 권총은 나중의 액션으로 사용하기 위해 저장할 수 없습니다.
====상처를 주는 카드(6)====
* 알바트로스 (3): 폭로자는 게임의 나머지 기간 동안 이 카드를 그들 앞에 얼굴을 비추게 합니다. 만약 어떤 시점에서 배에 총 2개의 알바트로스가 있다면, 그 배에 있는 모든 플레이어는 토르투가에 버려집니다. 예: 게임 초반에 일등 항해사가 알바트로스를 공개하고 그들 앞에 그것을 가지고 있습니다. 만약 그 일등 항해사의 배에 있는 누군가 (자신들을 포함하여) 또 다른 알바트로스를 공개하면, 그 배에 있는 모든 플레이어(심지어 알바트로스 카드가 없는 플레이어도)는 토르투가에 버려집니다. 만약 당신이 알바트로스 카드 2개를 가지고 배에 들어가면, 배에 있는 모든 사람(방금 배에 가입한 당신을 포함하여)은 즉시 토르투가에 버려집니다. 당신은 본질적으로 걷는 폭탄입니다. 알바트로스 카드는 토르투가에 아무런 영향을 미치지 않습니다. 만약 둘 이상의 플레이어가 알바트로스 카드에 빠져 동시에 토르투가에 들어오면, 그들은 순위를 뒤집습니다 (캐빈 보이는 토르투가에서 최고 순위의 오픈 폰 자리를 얻게 되고, 캡틴은 최악이 됩니다 등).
* Black Spot (3): Rebeller가 잠겼습니다.
====TREASURE MAPS (3)====
폭로자는 보물 지도를 다른 플레이어에게 줍니다. 카드가 주어진 플레이어가 보물 지도를 사용할 때, 그것은 액션으로 간주되지 않습니다. 플레이어는 여러 개의 보물 지도를 받고 소유할 수 있습니다. 2인용 및 3인용 게임에서 플레이어는 여전히 드러난 보물 지도를 다른 플레이어에게 주어야 합니다.
* 아틀란티스 (1): 소유자는 플레이어의 차례 직전에 한 배에서 다른 배의 라인 뒤쪽으로 이동할 수 있습니다 (자신의 차례 포함). 아틀란티스를 사용하는 것은 행동으로 간주되지 않습니다. 소유자는 토르투가나 노 젓는 배에서 배로 이동하기 위해 이 카드를 사용할 수 없습니다. 사용 후 폐기하십시오.
* 엘도라도 (1): 소유자는 즉시 투표 카드를 한 장 더 뽑습니다. 앞으로 있을 투표에서, 소유자는 보통 투표 카드 대신 두 장의 투표 카드를 사용할 수 있습니다. 엘도라도 (토투가에서 투표 카드가 잠기는 것을 줄여주는 사람들을 포함하여) 주어진 플레이어는 엘도라도 카드를 가지고 더 많은 투표 카드를 손에 유지하기 위해 그 능력을 사용하지 않을 수 있습니다. 투표에서 두 장의 카드를 사용한 후 엘도라도 카드를 버리세요.
* 젊음의 샘 (1): 소유자는 흑점을 드러내거나 권총으로 총을 맞거나 선장에게 유괴되거나 반란에 성공한 후 유괴되지 않기로 선택할 수 있습니다. 사용 후 폐기하십시오.
====스타드 카드 (각 게임에 무작위로 3개 추가)====
* 검은 가루: 폭로자는 폭발 토큰을 노 젓는 배에 놓습니다. 그 노 젓는 배는 게임의 나머지 부분에 사용되지 않을 수도 있습니다. 만약 플레이어가 현재 그 노 젓는 배에 있다면, 그들은 토르투가의 선 뒤쪽에 정박하게 됩니다. 노 젓는 배 없이 배로 이동하는 유일한 방법은 마르케 또는 아틀란티스의 편지를 사용하는 것입니다.
* 캐빈 피버: 폭로자가 다른 플레이어 1명을 선택합니다. 폭로자와 선택한 플레이어의 충성 카드는 뒤섞여 각각에게 재배포됩니다. 그들은 각각 비밀리에 새로운 충성 카드를 봅니다.
* 까마귀 둥지: 폭로자는 투표 데크에 한 플레이어의 투표 카드 손을 아래로 향하게 배치합니다. 그런 다음 폭로자는 개인적으로 해당 플레이어의 손에 있던 카드를 대체할 전체 투표 데크를 검색합니다. 완료 후 투표 데크를 섞습니다. 까마귀 둥지가 공개되었을 때 가지고 있던 것과 동일한 수의 투표 카드로 해당 플레이어의 손을 교체해야 합니다.
* 여덟 개의 종: 폭로자의 배나 섬에 있는 모든 졸개들은 주머니에 넣어지고 무작위로 그 배나 섬으로 다시 꺼내집니다. 폭로자가 혼자 있거나 노 젓는 배에 있으면 효과가 없습니다.
* 파사드: 폭로자는 오른쪽에 앉은 플레이어와 폰 위치를 바꿉니다.
* 해적 코드: 폭로자는 자신들이 속해 있었을 다음 두 표 (공격, 반란, 또는 싸움)에 참여하지 않을 수 있습니다. 만약 그렇게 할 수 있는 위치에 있다면 그들은 여전히 투표를 요청할 수 있습니다. 만약 그들이 투표를 위해 혼자 있다면, 투표 카드는 여전히 갑판에서 추가됩니다. 두 번째 투표에 참여하지 않은 후 폐기하세요.
* Scurvy: 폭로자를 포함하여 폭로자와 같은 배 또는 섬에 있는 모든 플레이어는 다음 순서를 잃습니다. 그 플레이어는 Scurvy 폭로자의 배 또는 섬에서 이동하더라도 여전히 다음 순서를 잃습니다. 순서를 잃는 플레이어는 스킵되지 않은 플레이어가 요청한 관련 싸움, 뮤티니 또는 공격에 여전히 참여할 수 있습니다. 2인용 게임에서 생략된 플레이어는 다음 순서에 대한 두 가지 동작을 모두 놓칩니다.
* 폭풍의 바다: 폭로자의 배에 있는 모든 보물은 (배에 있는 경우) 스페인 갈레온으로 돌아가거나 (토르투가에 있는 경우) 토르투가 보물은 원래의 시작 지역으로 돌아갑니다. 스페인 갈레온에 보물이 있다면, 갤레온에 있는 보물이 사라질 때까지 선장들은 서로의 배를 공격할 수 없습니다. 만약 폭로자가 보물이 없는 배에 있거나 노 젓는 배에 있다면 아무런 효과가 없습니다.
===게임 엔더 (1)===
* 스페인 아르마다: 스페인 아르마다 카드가 공개되면 게임이 끝납니다. 스페인 아르마다 카드가 마지막으로 남은 카드라면, 플레이어는 카드를 보거나 다른 플레이어에게 카드를 공개하도록 강요하는 동작을 사용하지 않을 수 있습니다.
346dba79e0de2833405e95f9d1671de9a73e2d41
1627
1613
2024-07-09T14:51:33Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 가슴을 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
==모든 플레이어:==
* 1.View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 2.이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 3.다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 4.이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
==투표 카드==
어택스, 뮤티니, 그리고 브롤스는 모든 종류의 투표입니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣을 것입니다. 각 투표 유형에 대해, 투표 데크의 맨 위 투표 카드도 추가됩니다. 그런 다음 가운데 있는 모든 카드가 섞이고 공개되며, 투표의 결과가 수행됩니다.
투표가 완료된 후, 모든 진행된 투표 카드를 투표 데크의 맨 아래에 얼굴을 아래로 향하게 섞고 배치합니다. 투표에 참여한 각 플레이어는 투표 데크의 맨 위에서 새로운 투표 카드를 뽑습니다.
==공격==
배의 선장은 그들의 행동으로 공격을 요청할 수 있습니다. 선장이 배 위에 유일한 플레이어라면, 그들은 여전히 공격을 요청할 수 있습니다. 공격하는 선장의 배에 있는 플레이어들만 투표에 참여합니다.
오직 투표 카드의 맨 위 부분만이 공격에서 중요하고 대포, 횃불 또는 물을 포함합니다. 모든 물은 1개의 횃불을 취소합니다. 만약 적어도 1개의 대포가 있고, 적어도 1개의 "성공적인" 횃불이 투표에서 재생되었다면, 선장은 스페인 갤리온에서 보물 1개를 가져가서 그들의 배에 고정시킬 수 있습니다.
스페인 갤리온호가 보물을 잃어버렸다면 선장은 다른 해적선(플라잉 더치맨 또는 졸리 로저)에 보관된 보물 중 하나를 가져가서 다른 선박에 전당포가 없더라도 둘 중 하나에 보관할 수 있습니다.
예: 대포 2개, 횃불 1개, 물 1개를 재생하면 물이 횃불을 취소하고 "성공한" 횃불이 없기 때문에 공격이 실패합니다.
예: 대포 1개, 횃불 2개, 물 1개를 플레이하면 대포가 1개이고 횃불 중 1개만 물에 의해 취소되어 1개의 "성공" 횃불이 남게 되므로 공격이 성공합니다.
예: 2개의 대포와 2개의 횃불을 연주하면 공격이 성공합니다. 하지만 여전히 보물은 1개만 가져갑니다.
브롤
토르투가 주지사는 그들의 행동으로 싸움을 요청할 수 있습니다. 만약 주지사가 토르투가의 유일한 플레이어라면, 그들은 여전히 싸움을 요청할 수 있습니다. 토르투가의 플레이어들만 투표에 참여합니다.
싸움에서는 투표 카드의 가운데 부분만 문제가 되며 영국 국기 또는 프랑스 국기 중 하나를 포함합니다. 드러난 카드 중 다수가 영국 국기라면, 영국 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 다수가 프랑스 국기라면, 프랑스 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 동점이면, 각 지역에 하나의 보물을 배치합니다. 토르투가에 있는 두 가지 보물은 항상 토르투가에 남아 있지만, 나중에 토르투가에 있는 지역 중 하나로 옮겨질 수도 있습니다.
==반란==
퍼스트 메이트(First Mate of Ship)는 반란을 행동으로 촉구할 수 있습니다. 선장을 제외한 해당 선박의 플레이어만 투표에 참여합니다.
반란은 표의 맨 아래 부분만 문제가 되고 해골이나 조타기 둘 중 하나를 포함합니다. 만약 밝혀진 카드 중 다수가 해골을 가지고 있다면, 반란을 일으키는 배의 선장은 토르투가에게 좌초됩니다. 과반수가 조타기를 가지고 있거나 동점을 가지고 있으면 아무 일도 일어나지 않습니다.
망연자실하기
배에 있는 졸개가 토르투가에 좌초되면, 같은 배의 뒤에 있는 졸개들이 빈 졸개 자리를 채우기 위해 위로 올라갑니다. 선장이 좌초되면, 1등 항해사가 선장이 됩니다. 배에 있는 모든 사람이 좌초되면, 그 배에 있는 보물은 같은 보물에 있는 그 배에 남아 있습니다. 그 보물은 게임 후반에 옮겨지지 않는 한 여전히 팀의 총 보물에 포함됩니다. 만약 플레이어가 빈 배에 탑승하면, 그들은 그 배의 선장이 됩니다.
토르투가에 정박해 있다면, 당신의 전당포는 토르투가의 선 뒤쪽에 놓이게 됩니다. 예를 들어, 만약 토르투가가 현재 비어있다면, "선의 뒤쪽"이 주지사의 위치입니다. 다른 예를 들어, 토르투가가 이미 2개의 전당포를 가지고 있다면, "선의 뒤쪽"은 "3" 위치입니다. 토르투가에 있는 동안 당신은 여전히 턴을 얻고 여전히 정상적으로 플레이어 액션을 수행할 수 있습니다.
만약 당신이 이미 토르투가에 있고 당신이 다시 석패를 당한다면, 당신에게 두 가지 일이 발생합니다. 첫째, 당신의 졸개는 토르투가의 줄 뒤쪽으로 이동되고 당신의 뒤에 순위가 매겨졌던 졸개들은 위로 올라갑니다. (만약 당신이 토르투가에 혼자 있다면 당신의 위치는 변하지 않습니다). 둘째, 당신의 투표 카드 중 하나는 다른 플레이어에 의해 무작위로 선택되고 투표 카드 덱의 맨 아래에 보이지 않게 배치됩니다. 당신은 남은 게임 동안 더 적은 수의 투표 카드로 게임을 하게 됩니다. 토르투가에 있는 동안 여러 번 석패를 당하면, 당신은 여러 투표 카드를 잃게 됩니다. 만약 당신이 투표 카드를 모두 잃는다면, 그렇게 할 수 있는 위치에 있다면 당신은 여전히 투표를 요청할 수 있지만 당신은 참여할 수 없을 것입니다.
==노 젓기 보트==
노 젓는 배로 이동하는 것은 한 가지 행동을 취합니다. 따라서 한 가지 행동으로 노 젓는 배로 이동하고 두 번째 행동으로 배나 토르투가로 이동해야 하기 때문에 토르투가에서 배로 또는 배에서 토르투가로 이동하는 데 총 두 가지 행동이 필요합니다. 현재 노 젓는 배에 전당포가 있는 경우 각 노 젓는 배에 한 번에 한 개의 전당포만 가지고 있기 때문에 다른 전당포는 그 노 젓는 배로 이동할 수 없습니다. 만약 여러분의 전당포가 노 젓는 배에 있다면 투표에 참여하지 않습니다. 다른 전당포를 차단하기 위해 노 젓는 배에 "앉아" 다른 행동(예: 카드 보기 및 공개)을 할 수 있습니다. 노 젓는 배에 타고 있다가 좌초된 경우에는 토르투가의 선 뒤쪽으로 전당포를 반납해야 하지만 투표 카드를 잃지는 않습니다.
==게임의 끝과 승리==
이벤트 덱이 다 떨어지고 공개되지 않은 이벤트 카드가 줄에 있는 5장 밖에 남지 않으면, 그 5장의 카드를 섞고 새로운 줄에 놓으세요. 스페인 아르마다 카드는 마지막 5장의 카드 중 하나가 될 것이고 공개된 카드는 더 이상 교체되지 않을 것입니다.
스페인 아르마다가 공개되면 즉시 보물이 가장 많은 팀이 게임에서 승리합니다. 게임이 끝나면 전당포가 어디에 있든 상관없이 팀과 함께 승리할 수 있습니다.
홀수 선수가 나오는 경기는 스페인 아르마다 카드가 공개됐을 때 팀이 비기면 네덜란드 선수가 이깁니다.
짝수 명의 플레이어가 있는 게임에서 스페인 아르마다 카드가 공개되었을 때 팀이 동점이 되면 게임에서 스페인 아르마다 카드를 제거하고 버려지고 공개되지 않은 모든 이벤트 카드를 새로운 이벤트 덱에 섞습니다. 알바트로스, 레터 오브 마르케 또는 보물 지도와 같이 현재 플레이어 앞에 있는 카드를 섞지 마십시오. 연속으로 5개의 새로운 이벤트 카드를 배치하고 중단한 곳에서 계속 플레이하십시오. 주도권을 잡은 첫 번째 팀이 게임에서 이깁니다.
==이벤트 카드==
아래 설명에서 모든 플레이어는 자신을 포함합니다. 다른 플레이어는 자신을 포함하지 않습니다. 모든 카드 해상도는 공개 시 필수입니다.
====유용한 카드(6)====
* 마크의 편지 (3): 드러버는 토르투가나 노 젓는 배에 있는 모든 플레이어를 두 배의 라인 뒤쪽으로 이동시킵니다. 드러버는 또한 이 카드를 저장하고 미래의 행동으로 사용할 수 있습니다.
* 권총 (3): 폭로자가 다른 플레이어를 선택합니다. 그 플레이어는 낙오되었습니다. 권총은 나중의 액션으로 사용하기 위해 저장할 수 없습니다.
====상처를 주는 카드(6)====
* 알바트로스 (3): 폭로자는 게임의 나머지 기간 동안 이 카드를 그들 앞에 얼굴을 비추게 합니다. 만약 어떤 시점에서 배에 총 2개의 알바트로스가 있다면, 그 배에 있는 모든 플레이어는 토르투가에 버려집니다. 예: 게임 초반에 일등 항해사가 알바트로스를 공개하고 그들 앞에 그것을 가지고 있습니다. 만약 그 일등 항해사의 배에 있는 누군가 (자신들을 포함하여) 또 다른 알바트로스를 공개하면, 그 배에 있는 모든 플레이어(심지어 알바트로스 카드가 없는 플레이어도)는 토르투가에 버려집니다. 만약 당신이 알바트로스 카드 2개를 가지고 배에 들어가면, 배에 있는 모든 사람(방금 배에 가입한 당신을 포함하여)은 즉시 토르투가에 버려집니다. 당신은 본질적으로 걷는 폭탄입니다. 알바트로스 카드는 토르투가에 아무런 영향을 미치지 않습니다. 만약 둘 이상의 플레이어가 알바트로스 카드에 빠져 동시에 토르투가에 들어오면, 그들은 순위를 뒤집습니다 (캐빈 보이는 토르투가에서 최고 순위의 오픈 폰 자리를 얻게 되고, 캡틴은 최악이 됩니다 등).
* Black Spot (3): Rebeller가 잠겼습니다.
====TREASURE MAPS (3)====
폭로자는 보물 지도를 다른 플레이어에게 줍니다. 카드가 주어진 플레이어가 보물 지도를 사용할 때, 그것은 액션으로 간주되지 않습니다. 플레이어는 여러 개의 보물 지도를 받고 소유할 수 있습니다. 2인용 및 3인용 게임에서 플레이어는 여전히 드러난 보물 지도를 다른 플레이어에게 주어야 합니다.
* 아틀란티스 (1): 소유자는 플레이어의 차례 직전에 한 배에서 다른 배의 라인 뒤쪽으로 이동할 수 있습니다 (자신의 차례 포함). 아틀란티스를 사용하는 것은 행동으로 간주되지 않습니다. 소유자는 토르투가나 노 젓는 배에서 배로 이동하기 위해 이 카드를 사용할 수 없습니다. 사용 후 폐기하십시오.
* 엘도라도 (1): 소유자는 즉시 투표 카드를 한 장 더 뽑습니다. 앞으로 있을 투표에서, 소유자는 보통 투표 카드 대신 두 장의 투표 카드를 사용할 수 있습니다. 엘도라도 (토투가에서 투표 카드가 잠기는 것을 줄여주는 사람들을 포함하여) 주어진 플레이어는 엘도라도 카드를 가지고 더 많은 투표 카드를 손에 유지하기 위해 그 능력을 사용하지 않을 수 있습니다. 투표에서 두 장의 카드를 사용한 후 엘도라도 카드를 버리세요.
* 젊음의 샘 (1): 소유자는 흑점을 드러내거나 권총으로 총을 맞거나 선장에게 유괴되거나 반란에 성공한 후 유괴되지 않기로 선택할 수 있습니다. 사용 후 폐기하십시오.
====스타드 카드 (각 게임에 무작위로 3개 추가)====
* 검은 가루: 폭로자는 폭발 토큰을 노 젓는 배에 놓습니다. 그 노 젓는 배는 게임의 나머지 부분에 사용되지 않을 수도 있습니다. 만약 플레이어가 현재 그 노 젓는 배에 있다면, 그들은 토르투가의 선 뒤쪽에 정박하게 됩니다. 노 젓는 배 없이 배로 이동하는 유일한 방법은 마르케 또는 아틀란티스의 편지를 사용하는 것입니다.
* 캐빈 피버: 폭로자가 다른 플레이어 1명을 선택합니다. 폭로자와 선택한 플레이어의 충성 카드는 뒤섞여 각각에게 재배포됩니다. 그들은 각각 비밀리에 새로운 충성 카드를 봅니다.
* 까마귀 둥지: 폭로자는 투표 데크에 한 플레이어의 투표 카드 손을 아래로 향하게 배치합니다. 그런 다음 폭로자는 개인적으로 해당 플레이어의 손에 있던 카드를 대체할 전체 투표 데크를 검색합니다. 완료 후 투표 데크를 섞습니다. 까마귀 둥지가 공개되었을 때 가지고 있던 것과 동일한 수의 투표 카드로 해당 플레이어의 손을 교체해야 합니다.
* 여덟 개의 종: 폭로자의 배나 섬에 있는 모든 졸개들은 주머니에 넣어지고 무작위로 그 배나 섬으로 다시 꺼내집니다. 폭로자가 혼자 있거나 노 젓는 배에 있으면 효과가 없습니다.
* 파사드: 폭로자는 오른쪽에 앉은 플레이어와 폰 위치를 바꿉니다.
* 해적 코드: 폭로자는 자신들이 속해 있었을 다음 두 표 (공격, 반란, 또는 싸움)에 참여하지 않을 수 있습니다. 만약 그렇게 할 수 있는 위치에 있다면 그들은 여전히 투표를 요청할 수 있습니다. 만약 그들이 투표를 위해 혼자 있다면, 투표 카드는 여전히 갑판에서 추가됩니다. 두 번째 투표에 참여하지 않은 후 폐기하세요.
* Scurvy: 폭로자를 포함하여 폭로자와 같은 배 또는 섬에 있는 모든 플레이어는 다음 순서를 잃습니다. 그 플레이어는 Scurvy 폭로자의 배 또는 섬에서 이동하더라도 여전히 다음 순서를 잃습니다. 순서를 잃는 플레이어는 스킵되지 않은 플레이어가 요청한 관련 싸움, 뮤티니 또는 공격에 여전히 참여할 수 있습니다. 2인용 게임에서 생략된 플레이어는 다음 순서에 대한 두 가지 동작을 모두 놓칩니다.
* 폭풍의 바다: 폭로자의 배에 있는 모든 보물은 (배에 있는 경우) 스페인 갈레온으로 돌아가거나 (토르투가에 있는 경우) 토르투가 보물은 원래의 시작 지역으로 돌아갑니다. 스페인 갈레온에 보물이 있다면, 갤레온에 있는 보물이 사라질 때까지 선장들은 서로의 배를 공격할 수 없습니다. 만약 폭로자가 보물이 없는 배에 있거나 노 젓는 배에 있다면 아무런 효과가 없습니다.
===게임 엔더 (1)===
* 스페인 아르마다: 스페인 아르마다 카드가 공개되면 게임이 끝납니다. 스페인 아르마다 카드가 마지막으로 남은 카드라면, 플레이어는 카드를 보거나 다른 플레이어에게 카드를 공개하도록 강요하는 동작을 사용하지 않을 수 있습니다.
bbfbb261901738d5b4f3545be858fadad8801f07
1628
1627
2024-07-09T14:53:46Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 보물상자를 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
==모든 플레이어:==
* 1.View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 2.이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 3.다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 4.이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
==투표 카드==
어택스, 뮤티니, 그리고 브롤스는 모든 종류의 투표입니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣을 것입니다. 각 투표 유형에 대해, 투표 데크의 맨 위 투표 카드도 추가됩니다. 그런 다음 가운데 있는 모든 카드가 섞이고 공개되며, 투표의 결과가 수행됩니다.
투표가 완료된 후, 모든 진행된 투표 카드를 투표 데크의 맨 아래에 얼굴을 아래로 향하게 섞고 배치합니다. 투표에 참여한 각 플레이어는 투표 데크의 맨 위에서 새로운 투표 카드를 뽑습니다.
==공격==
배의 선장은 그들의 행동으로 공격을 요청할 수 있습니다. 선장이 배 위에 유일한 플레이어라면, 그들은 여전히 공격을 요청할 수 있습니다. 공격하는 선장의 배에 있는 플레이어들만 투표에 참여합니다.
오직 투표 카드의 맨 위 부분만이 공격에서 중요하고 대포, 횃불 또는 물을 포함합니다. 모든 물은 1개의 횃불을 취소합니다. 만약 적어도 1개의 대포가 있고, 적어도 1개의 "성공적인" 횃불이 투표에서 재생되었다면, 선장은 스페인 갤리온에서 보물 1개를 가져가서 그들의 배에 고정시킬 수 있습니다.
스페인 갤리온호가 보물을 잃어버렸다면 선장은 다른 해적선(플라잉 더치맨 또는 졸리 로저)에 보관된 보물 중 하나를 가져가서 다른 선박에 전당포가 없더라도 둘 중 하나에 보관할 수 있습니다.
예: 대포 2개, 횃불 1개, 물 1개를 재생하면 물이 횃불을 취소하고 "성공한" 횃불이 없기 때문에 공격이 실패합니다.
예: 대포 1개, 횃불 2개, 물 1개를 플레이하면 대포가 1개이고 횃불 중 1개만 물에 의해 취소되어 1개의 "성공" 횃불이 남게 되므로 공격이 성공합니다.
예: 2개의 대포와 2개의 횃불을 연주하면 공격이 성공합니다. 하지만 여전히 보물은 1개만 가져갑니다.
브롤
토르투가 주지사는 그들의 행동으로 싸움을 요청할 수 있습니다. 만약 주지사가 토르투가의 유일한 플레이어라면, 그들은 여전히 싸움을 요청할 수 있습니다. 토르투가의 플레이어들만 투표에 참여합니다.
싸움에서는 투표 카드의 가운데 부분만 문제가 되며 영국 국기 또는 프랑스 국기 중 하나를 포함합니다. 드러난 카드 중 다수가 영국 국기라면, 영국 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 다수가 프랑스 국기라면, 프랑스 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 동점이면, 각 지역에 하나의 보물을 배치합니다. 토르투가에 있는 두 가지 보물은 항상 토르투가에 남아 있지만, 나중에 토르투가에 있는 지역 중 하나로 옮겨질 수도 있습니다.
==반란==
퍼스트 메이트(First Mate of Ship)는 반란을 행동으로 촉구할 수 있습니다. 선장을 제외한 해당 선박의 플레이어만 투표에 참여합니다.
반란은 표의 맨 아래 부분만 문제가 되고 해골이나 조타기 둘 중 하나를 포함합니다. 만약 밝혀진 카드 중 다수가 해골을 가지고 있다면, 반란을 일으키는 배의 선장은 토르투가에게 좌초됩니다. 과반수가 조타기를 가지고 있거나 동점을 가지고 있으면 아무 일도 일어나지 않습니다.
망연자실하기
배에 있는 졸개가 토르투가에 좌초되면, 같은 배의 뒤에 있는 졸개들이 빈 졸개 자리를 채우기 위해 위로 올라갑니다. 선장이 좌초되면, 1등 항해사가 선장이 됩니다. 배에 있는 모든 사람이 좌초되면, 그 배에 있는 보물은 같은 보물에 있는 그 배에 남아 있습니다. 그 보물은 게임 후반에 옮겨지지 않는 한 여전히 팀의 총 보물에 포함됩니다. 만약 플레이어가 빈 배에 탑승하면, 그들은 그 배의 선장이 됩니다.
토르투가에 정박해 있다면, 당신의 전당포는 토르투가의 선 뒤쪽에 놓이게 됩니다. 예를 들어, 만약 토르투가가 현재 비어있다면, "선의 뒤쪽"이 주지사의 위치입니다. 다른 예를 들어, 토르투가가 이미 2개의 전당포를 가지고 있다면, "선의 뒤쪽"은 "3" 위치입니다. 토르투가에 있는 동안 당신은 여전히 턴을 얻고 여전히 정상적으로 플레이어 액션을 수행할 수 있습니다.
만약 당신이 이미 토르투가에 있고 당신이 다시 석패를 당한다면, 당신에게 두 가지 일이 발생합니다. 첫째, 당신의 졸개는 토르투가의 줄 뒤쪽으로 이동되고 당신의 뒤에 순위가 매겨졌던 졸개들은 위로 올라갑니다. (만약 당신이 토르투가에 혼자 있다면 당신의 위치는 변하지 않습니다). 둘째, 당신의 투표 카드 중 하나는 다른 플레이어에 의해 무작위로 선택되고 투표 카드 덱의 맨 아래에 보이지 않게 배치됩니다. 당신은 남은 게임 동안 더 적은 수의 투표 카드로 게임을 하게 됩니다. 토르투가에 있는 동안 여러 번 석패를 당하면, 당신은 여러 투표 카드를 잃게 됩니다. 만약 당신이 투표 카드를 모두 잃는다면, 그렇게 할 수 있는 위치에 있다면 당신은 여전히 투표를 요청할 수 있지만 당신은 참여할 수 없을 것입니다.
==노 젓기 보트==
노 젓는 배로 이동하는 것은 한 가지 행동을 취합니다. 따라서 한 가지 행동으로 노 젓는 배로 이동하고 두 번째 행동으로 배나 토르투가로 이동해야 하기 때문에 토르투가에서 배로 또는 배에서 토르투가로 이동하는 데 총 두 가지 행동이 필요합니다. 현재 노 젓는 배에 전당포가 있는 경우 각 노 젓는 배에 한 번에 한 개의 전당포만 가지고 있기 때문에 다른 전당포는 그 노 젓는 배로 이동할 수 없습니다. 만약 여러분의 전당포가 노 젓는 배에 있다면 투표에 참여하지 않습니다. 다른 전당포를 차단하기 위해 노 젓는 배에 "앉아" 다른 행동(예: 카드 보기 및 공개)을 할 수 있습니다. 노 젓는 배에 타고 있다가 좌초된 경우에는 토르투가의 선 뒤쪽으로 전당포를 반납해야 하지만 투표 카드를 잃지는 않습니다.
==게임의 끝과 승리==
이벤트 덱이 다 떨어지고 공개되지 않은 이벤트 카드가 줄에 있는 5장 밖에 남지 않으면, 그 5장의 카드를 섞고 새로운 줄에 놓으세요. 스페인 아르마다 카드는 마지막 5장의 카드 중 하나가 될 것이고 공개된 카드는 더 이상 교체되지 않을 것입니다.
스페인 아르마다가 공개되면 즉시 보물이 가장 많은 팀이 게임에서 승리합니다. 게임이 끝나면 전당포가 어디에 있든 상관없이 팀과 함께 승리할 수 있습니다.
홀수 선수가 나오는 경기는 스페인 아르마다 카드가 공개됐을 때 팀이 비기면 네덜란드 선수가 이깁니다.
짝수 명의 플레이어가 있는 게임에서 스페인 아르마다 카드가 공개되었을 때 팀이 동점이 되면 게임에서 스페인 아르마다 카드를 제거하고 버려지고 공개되지 않은 모든 이벤트 카드를 새로운 이벤트 덱에 섞습니다. 알바트로스, 레터 오브 마르케 또는 보물 지도와 같이 현재 플레이어 앞에 있는 카드를 섞지 마십시오. 연속으로 5개의 새로운 이벤트 카드를 배치하고 중단한 곳에서 계속 플레이하십시오. 주도권을 잡은 첫 번째 팀이 게임에서 이깁니다.
==이벤트 카드==
아래 설명에서 모든 플레이어는 자신을 포함합니다. 다른 플레이어는 자신을 포함하지 않습니다. 모든 카드 해상도는 공개 시 필수입니다.
====유용한 카드(6)====
* 마크의 편지 (3): 드러버는 토르투가나 노 젓는 배에 있는 모든 플레이어를 두 배의 라인 뒤쪽으로 이동시킵니다. 드러버는 또한 이 카드를 저장하고 미래의 행동으로 사용할 수 있습니다.
* 권총 (3): 폭로자가 다른 플레이어를 선택합니다. 그 플레이어는 낙오되었습니다. 권총은 나중의 액션으로 사용하기 위해 저장할 수 없습니다.
====상처를 주는 카드(6)====
* 알바트로스 (3): 폭로자는 게임의 나머지 기간 동안 이 카드를 그들 앞에 얼굴을 비추게 합니다. 만약 어떤 시점에서 배에 총 2개의 알바트로스가 있다면, 그 배에 있는 모든 플레이어는 토르투가에 버려집니다. 예: 게임 초반에 일등 항해사가 알바트로스를 공개하고 그들 앞에 그것을 가지고 있습니다. 만약 그 일등 항해사의 배에 있는 누군가 (자신들을 포함하여) 또 다른 알바트로스를 공개하면, 그 배에 있는 모든 플레이어(심지어 알바트로스 카드가 없는 플레이어도)는 토르투가에 버려집니다. 만약 당신이 알바트로스 카드 2개를 가지고 배에 들어가면, 배에 있는 모든 사람(방금 배에 가입한 당신을 포함하여)은 즉시 토르투가에 버려집니다. 당신은 본질적으로 걷는 폭탄입니다. 알바트로스 카드는 토르투가에 아무런 영향을 미치지 않습니다. 만약 둘 이상의 플레이어가 알바트로스 카드에 빠져 동시에 토르투가에 들어오면, 그들은 순위를 뒤집습니다 (캐빈 보이는 토르투가에서 최고 순위의 오픈 폰 자리를 얻게 되고, 캡틴은 최악이 됩니다 등).
* Black Spot (3): Rebeller가 잠겼습니다.
====TREASURE MAPS (3)====
폭로자는 보물 지도를 다른 플레이어에게 줍니다. 카드가 주어진 플레이어가 보물 지도를 사용할 때, 그것은 액션으로 간주되지 않습니다. 플레이어는 여러 개의 보물 지도를 받고 소유할 수 있습니다. 2인용 및 3인용 게임에서 플레이어는 여전히 드러난 보물 지도를 다른 플레이어에게 주어야 합니다.
* 아틀란티스 (1): 소유자는 플레이어의 차례 직전에 한 배에서 다른 배의 라인 뒤쪽으로 이동할 수 있습니다 (자신의 차례 포함). 아틀란티스를 사용하는 것은 행동으로 간주되지 않습니다. 소유자는 토르투가나 노 젓는 배에서 배로 이동하기 위해 이 카드를 사용할 수 없습니다. 사용 후 폐기하십시오.
* 엘도라도 (1): 소유자는 즉시 투표 카드를 한 장 더 뽑습니다. 앞으로 있을 투표에서, 소유자는 보통 투표 카드 대신 두 장의 투표 카드를 사용할 수 있습니다. 엘도라도 (토투가에서 투표 카드가 잠기는 것을 줄여주는 사람들을 포함하여) 주어진 플레이어는 엘도라도 카드를 가지고 더 많은 투표 카드를 손에 유지하기 위해 그 능력을 사용하지 않을 수 있습니다. 투표에서 두 장의 카드를 사용한 후 엘도라도 카드를 버리세요.
* 젊음의 샘 (1): 소유자는 흑점을 드러내거나 권총으로 총을 맞거나 선장에게 유괴되거나 반란에 성공한 후 유괴되지 않기로 선택할 수 있습니다. 사용 후 폐기하십시오.
====스타드 카드 (각 게임에 무작위로 3개 추가)====
* 검은 가루: 폭로자는 폭발 토큰을 노 젓는 배에 놓습니다. 그 노 젓는 배는 게임의 나머지 부분에 사용되지 않을 수도 있습니다. 만약 플레이어가 현재 그 노 젓는 배에 있다면, 그들은 토르투가의 선 뒤쪽에 정박하게 됩니다. 노 젓는 배 없이 배로 이동하는 유일한 방법은 마르케 또는 아틀란티스의 편지를 사용하는 것입니다.
* 캐빈 피버: 폭로자가 다른 플레이어 1명을 선택합니다. 폭로자와 선택한 플레이어의 충성 카드는 뒤섞여 각각에게 재배포됩니다. 그들은 각각 비밀리에 새로운 충성 카드를 봅니다.
* 까마귀 둥지: 폭로자는 투표 데크에 한 플레이어의 투표 카드 손을 아래로 향하게 배치합니다. 그런 다음 폭로자는 개인적으로 해당 플레이어의 손에 있던 카드를 대체할 전체 투표 데크를 검색합니다. 완료 후 투표 데크를 섞습니다. 까마귀 둥지가 공개되었을 때 가지고 있던 것과 동일한 수의 투표 카드로 해당 플레이어의 손을 교체해야 합니다.
* 여덟 개의 종: 폭로자의 배나 섬에 있는 모든 졸개들은 주머니에 넣어지고 무작위로 그 배나 섬으로 다시 꺼내집니다. 폭로자가 혼자 있거나 노 젓는 배에 있으면 효과가 없습니다.
* 파사드: 폭로자는 오른쪽에 앉은 플레이어와 폰 위치를 바꿉니다.
* 해적 코드: 폭로자는 자신들이 속해 있었을 다음 두 표 (공격, 반란, 또는 싸움)에 참여하지 않을 수 있습니다. 만약 그렇게 할 수 있는 위치에 있다면 그들은 여전히 투표를 요청할 수 있습니다. 만약 그들이 투표를 위해 혼자 있다면, 투표 카드는 여전히 갑판에서 추가됩니다. 두 번째 투표에 참여하지 않은 후 폐기하세요.
* Scurvy: 폭로자를 포함하여 폭로자와 같은 배 또는 섬에 있는 모든 플레이어는 다음 순서를 잃습니다. 그 플레이어는 Scurvy 폭로자의 배 또는 섬에서 이동하더라도 여전히 다음 순서를 잃습니다. 순서를 잃는 플레이어는 스킵되지 않은 플레이어가 요청한 관련 싸움, 뮤티니 또는 공격에 여전히 참여할 수 있습니다. 2인용 게임에서 생략된 플레이어는 다음 순서에 대한 두 가지 동작을 모두 놓칩니다.
* 폭풍의 바다: 폭로자의 배에 있는 모든 보물은 (배에 있는 경우) 스페인 갈레온으로 돌아가거나 (토르투가에 있는 경우) 토르투가 보물은 원래의 시작 지역으로 돌아갑니다. 스페인 갈레온에 보물이 있다면, 갤레온에 있는 보물이 사라질 때까지 선장들은 서로의 배를 공격할 수 없습니다. 만약 폭로자가 보물이 없는 배에 있거나 노 젓는 배에 있다면 아무런 효과가 없습니다.
===게임 엔더 (1)===
* 스페인 아르마다: 스페인 아르마다 카드가 공개되면 게임이 끝납니다. 스페인 아르마다 카드가 마지막으로 남은 카드라면, 플레이어는 카드를 보거나 다른 플레이어에게 카드를 공개하도록 강요하는 동작을 사용하지 않을 수 있습니다.
a789de9c5a12fa8fdfc7a45b2c9699dd1ab5a4af
1629
1628
2024-07-09T14:59:21Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 보물상자를 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
===모든 플레이어:===
* 1.View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 2.이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 3.다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 4.이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
1.캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
2.퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
3.캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
4.주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
===투표 카드===
어택스, 뮤티니, 그리고 브롤스는 모든 종류의 투표입니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣을 것입니다. 각 투표 유형에 대해, 투표 데크의 맨 위 투표 카드도 추가됩니다. 그런 다음 가운데 있는 모든 카드가 섞이고 공개되며, 투표의 결과가 수행됩니다.
투표가 완료된 후, 모든 진행된 투표 카드를 투표 데크의 맨 아래에 얼굴을 아래로 향하게 섞고 배치합니다. 투표에 참여한 각 플레이어는 투표 데크의 맨 위에서 새로운 투표 카드를 뽑습니다.
===공격===
배의 선장은 그들의 행동으로 공격을 요청할 수 있습니다. 선장이 배 위에 유일한 플레이어라면, 그들은 여전히 공격을 요청할 수 있습니다. 공격하는 선장의 배에 있는 플레이어들만 투표에 참여합니다.
오직 투표 카드의 맨 위 부분만이 공격에서 중요하고 대포, 횃불 또는 물을 포함합니다. 모든 물은 1개의 횃불을 취소합니다. 만약 적어도 1개의 대포가 있고, 적어도 1개의 "성공적인" 횃불이 투표에서 재생되었다면, 선장은 스페인 갤리온에서 보물 1개를 가져가서 그들의 배에 고정시킬 수 있습니다.
스페인 갤리온호가 보물을 잃어버렸다면 선장은 다른 해적선(플라잉 더치맨 또는 졸리 로저)에 보관된 보물 중 하나를 가져가서 다른 선박에 전당포가 없더라도 둘 중 하나에 보관할 수 있습니다.
예: 대포 2개, 횃불 1개, 물 1개를 재생하면 물이 횃불을 취소하고 "성공한" 횃불이 없기 때문에 공격이 실패합니다.
예: 대포 1개, 횃불 2개, 물 1개를 플레이하면 대포가 1개이고 횃불 중 1개만 물에 의해 취소되어 1개의 "성공" 횃불이 남게 되므로 공격이 성공합니다.
예: 2개의 대포와 2개의 횃불을 연주하면 공격이 성공합니다. 하지만 여전히 보물은 1개만 가져갑니다.
브롤
토르투가 주지사는 그들의 행동으로 싸움을 요청할 수 있습니다. 만약 주지사가 토르투가의 유일한 플레이어라면, 그들은 여전히 싸움을 요청할 수 있습니다. 토르투가의 플레이어들만 투표에 참여합니다.
싸움에서는 투표 카드의 가운데 부분만 문제가 되며 영국 국기 또는 프랑스 국기 중 하나를 포함합니다. 드러난 카드 중 다수가 영국 국기라면, 영국 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 다수가 프랑스 국기라면, 프랑스 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 동점이면, 각 지역에 하나의 보물을 배치합니다. 토르투가에 있는 두 가지 보물은 항상 토르투가에 남아 있지만, 나중에 토르투가에 있는 지역 중 하나로 옮겨질 수도 있습니다.
===반란===
퍼스트 메이트(First Mate of Ship)는 반란을 행동으로 촉구할 수 있습니다. 선장을 제외한 해당 선박의 플레이어만 투표에 참여합니다.
반란은 표의 맨 아래 부분만 문제가 되고 해골이나 조타기 둘 중 하나를 포함합니다. 만약 밝혀진 카드 중 다수가 해골을 가지고 있다면, 반란을 일으키는 배의 선장은 토르투가에게 좌초됩니다. 과반수가 조타기를 가지고 있거나 동점을 가지고 있으면 아무 일도 일어나지 않습니다.
망연자실하기
배에 있는 졸개가 토르투가에 좌초되면, 같은 배의 뒤에 있는 졸개들이 빈 졸개 자리를 채우기 위해 위로 올라갑니다. 선장이 좌초되면, 1등 항해사가 선장이 됩니다. 배에 있는 모든 사람이 좌초되면, 그 배에 있는 보물은 같은 보물에 있는 그 배에 남아 있습니다. 그 보물은 게임 후반에 옮겨지지 않는 한 여전히 팀의 총 보물에 포함됩니다. 만약 플레이어가 빈 배에 탑승하면, 그들은 그 배의 선장이 됩니다.
토르투가에 정박해 있다면, 당신의 전당포는 토르투가의 선 뒤쪽에 놓이게 됩니다. 예를 들어, 만약 토르투가가 현재 비어있다면, "선의 뒤쪽"이 주지사의 위치입니다. 다른 예를 들어, 토르투가가 이미 2개의 전당포를 가지고 있다면, "선의 뒤쪽"은 "3" 위치입니다. 토르투가에 있는 동안 당신은 여전히 턴을 얻고 여전히 정상적으로 플레이어 액션을 수행할 수 있습니다.
만약 당신이 이미 토르투가에 있고 당신이 다시 석패를 당한다면, 당신에게 두 가지 일이 발생합니다. 첫째, 당신의 졸개는 토르투가의 줄 뒤쪽으로 이동되고 당신의 뒤에 순위가 매겨졌던 졸개들은 위로 올라갑니다. (만약 당신이 토르투가에 혼자 있다면 당신의 위치는 변하지 않습니다). 둘째, 당신의 투표 카드 중 하나는 다른 플레이어에 의해 무작위로 선택되고 투표 카드 덱의 맨 아래에 보이지 않게 배치됩니다. 당신은 남은 게임 동안 더 적은 수의 투표 카드로 게임을 하게 됩니다. 토르투가에 있는 동안 여러 번 석패를 당하면, 당신은 여러 투표 카드를 잃게 됩니다. 만약 당신이 투표 카드를 모두 잃는다면, 그렇게 할 수 있는 위치에 있다면 당신은 여전히 투표를 요청할 수 있지만 당신은 참여할 수 없을 것입니다.
===노 젓기 보트===
노 젓는 배로 이동하는 것은 한 가지 행동을 취합니다. 따라서 한 가지 행동으로 노 젓는 배로 이동하고 두 번째 행동으로 배나 토르투가로 이동해야 하기 때문에 토르투가에서 배로 또는 배에서 토르투가로 이동하는 데 총 두 가지 행동이 필요합니다. 현재 노 젓는 배에 전당포가 있는 경우 각 노 젓는 배에 한 번에 한 개의 전당포만 가지고 있기 때문에 다른 전당포는 그 노 젓는 배로 이동할 수 없습니다. 만약 여러분의 전당포가 노 젓는 배에 있다면 투표에 참여하지 않습니다. 다른 전당포를 차단하기 위해 노 젓는 배에 "앉아" 다른 행동(예: 카드 보기 및 공개)을 할 수 있습니다. 노 젓는 배에 타고 있다가 좌초된 경우에는 토르투가의 선 뒤쪽으로 전당포를 반납해야 하지만 투표 카드를 잃지는 않습니다.
==게임의 끝과 승리==
이벤트 덱이 다 떨어지고 공개되지 않은 이벤트 카드가 줄에 있는 5장 밖에 남지 않으면, 그 5장의 카드를 섞고 새로운 줄에 놓으세요. 스페인 아르마다 카드는 마지막 5장의 카드 중 하나가 될 것이고 공개된 카드는 더 이상 교체되지 않을 것입니다.
스페인 아르마다가 공개되면 즉시 보물이 가장 많은 팀이 게임에서 승리합니다. 게임이 끝나면 전당포가 어디에 있든 상관없이 팀과 함께 승리할 수 있습니다.
홀수 선수가 나오는 경기는 스페인 아르마다 카드가 공개됐을 때 팀이 비기면 네덜란드 선수가 이깁니다.
짝수 명의 플레이어가 있는 게임에서 스페인 아르마다 카드가 공개되었을 때 팀이 동점이 되면 게임에서 스페인 아르마다 카드를 제거하고 버려지고 공개되지 않은 모든 이벤트 카드를 새로운 이벤트 덱에 섞습니다. 알바트로스, 레터 오브 마르케 또는 보물 지도와 같이 현재 플레이어 앞에 있는 카드를 섞지 마십시오. 연속으로 5개의 새로운 이벤트 카드를 배치하고 중단한 곳에서 계속 플레이하십시오. 주도권을 잡은 첫 번째 팀이 게임에서 이깁니다.
==이벤트 카드==
아래 설명에서 모든 플레이어는 자신을 포함합니다. 다른 플레이어는 자신을 포함하지 않습니다. 모든 카드 해상도는 공개 시 필수입니다.
====유용한 카드(6)====
* 마크의 편지 (3): 드러버는 토르투가나 노 젓는 배에 있는 모든 플레이어를 두 배의 라인 뒤쪽으로 이동시킵니다. 드러버는 또한 이 카드를 저장하고 미래의 행동으로 사용할 수 있습니다.
* 권총 (3): 폭로자가 다른 플레이어를 선택합니다. 그 플레이어는 낙오되었습니다. 권총은 나중의 액션으로 사용하기 위해 저장할 수 없습니다.
====상처를 주는 카드(6)====
* 알바트로스 (3): 폭로자는 게임의 나머지 기간 동안 이 카드를 그들 앞에 얼굴을 비추게 합니다. 만약 어떤 시점에서 배에 총 2개의 알바트로스가 있다면, 그 배에 있는 모든 플레이어는 토르투가에 버려집니다. 예: 게임 초반에 일등 항해사가 알바트로스를 공개하고 그들 앞에 그것을 가지고 있습니다. 만약 그 일등 항해사의 배에 있는 누군가 (자신들을 포함하여) 또 다른 알바트로스를 공개하면, 그 배에 있는 모든 플레이어(심지어 알바트로스 카드가 없는 플레이어도)는 토르투가에 버려집니다. 만약 당신이 알바트로스 카드 2개를 가지고 배에 들어가면, 배에 있는 모든 사람(방금 배에 가입한 당신을 포함하여)은 즉시 토르투가에 버려집니다. 당신은 본질적으로 걷는 폭탄입니다. 알바트로스 카드는 토르투가에 아무런 영향을 미치지 않습니다. 만약 둘 이상의 플레이어가 알바트로스 카드에 빠져 동시에 토르투가에 들어오면, 그들은 순위를 뒤집습니다 (캐빈 보이는 토르투가에서 최고 순위의 오픈 폰 자리를 얻게 되고, 캡틴은 최악이 됩니다 등).
* Black Spot (3): Rebeller가 잠겼습니다.
====TREASURE MAPS (3)====
폭로자는 보물 지도를 다른 플레이어에게 줍니다. 카드가 주어진 플레이어가 보물 지도를 사용할 때, 그것은 액션으로 간주되지 않습니다. 플레이어는 여러 개의 보물 지도를 받고 소유할 수 있습니다. 2인용 및 3인용 게임에서 플레이어는 여전히 드러난 보물 지도를 다른 플레이어에게 주어야 합니다.
* 아틀란티스 (1): 소유자는 플레이어의 차례 직전에 한 배에서 다른 배의 라인 뒤쪽으로 이동할 수 있습니다 (자신의 차례 포함). 아틀란티스를 사용하는 것은 행동으로 간주되지 않습니다. 소유자는 토르투가나 노 젓는 배에서 배로 이동하기 위해 이 카드를 사용할 수 없습니다. 사용 후 폐기하십시오.
* 엘도라도 (1): 소유자는 즉시 투표 카드를 한 장 더 뽑습니다. 앞으로 있을 투표에서, 소유자는 보통 투표 카드 대신 두 장의 투표 카드를 사용할 수 있습니다. 엘도라도 (토투가에서 투표 카드가 잠기는 것을 줄여주는 사람들을 포함하여) 주어진 플레이어는 엘도라도 카드를 가지고 더 많은 투표 카드를 손에 유지하기 위해 그 능력을 사용하지 않을 수 있습니다. 투표에서 두 장의 카드를 사용한 후 엘도라도 카드를 버리세요.
* 젊음의 샘 (1): 소유자는 흑점을 드러내거나 권총으로 총을 맞거나 선장에게 유괴되거나 반란에 성공한 후 유괴되지 않기로 선택할 수 있습니다. 사용 후 폐기하십시오.
====스타드 카드 (각 게임에 무작위로 3개 추가)====
* 검은 가루: 폭로자는 폭발 토큰을 노 젓는 배에 놓습니다. 그 노 젓는 배는 게임의 나머지 부분에 사용되지 않을 수도 있습니다. 만약 플레이어가 현재 그 노 젓는 배에 있다면, 그들은 토르투가의 선 뒤쪽에 정박하게 됩니다. 노 젓는 배 없이 배로 이동하는 유일한 방법은 마르케 또는 아틀란티스의 편지를 사용하는 것입니다.
* 캐빈 피버: 폭로자가 다른 플레이어 1명을 선택합니다. 폭로자와 선택한 플레이어의 충성 카드는 뒤섞여 각각에게 재배포됩니다. 그들은 각각 비밀리에 새로운 충성 카드를 봅니다.
* 까마귀 둥지: 폭로자는 투표 데크에 한 플레이어의 투표 카드 손을 아래로 향하게 배치합니다. 그런 다음 폭로자는 개인적으로 해당 플레이어의 손에 있던 카드를 대체할 전체 투표 데크를 검색합니다. 완료 후 투표 데크를 섞습니다. 까마귀 둥지가 공개되었을 때 가지고 있던 것과 동일한 수의 투표 카드로 해당 플레이어의 손을 교체해야 합니다.
* 여덟 개의 종: 폭로자의 배나 섬에 있는 모든 졸개들은 주머니에 넣어지고 무작위로 그 배나 섬으로 다시 꺼내집니다. 폭로자가 혼자 있거나 노 젓는 배에 있으면 효과가 없습니다.
* 파사드: 폭로자는 오른쪽에 앉은 플레이어와 폰 위치를 바꿉니다.
* 해적 코드: 폭로자는 자신들이 속해 있었을 다음 두 표 (공격, 반란, 또는 싸움)에 참여하지 않을 수 있습니다. 만약 그렇게 할 수 있는 위치에 있다면 그들은 여전히 투표를 요청할 수 있습니다. 만약 그들이 투표를 위해 혼자 있다면, 투표 카드는 여전히 갑판에서 추가됩니다. 두 번째 투표에 참여하지 않은 후 폐기하세요.
* Scurvy: 폭로자를 포함하여 폭로자와 같은 배 또는 섬에 있는 모든 플레이어는 다음 순서를 잃습니다. 그 플레이어는 Scurvy 폭로자의 배 또는 섬에서 이동하더라도 여전히 다음 순서를 잃습니다. 순서를 잃는 플레이어는 스킵되지 않은 플레이어가 요청한 관련 싸움, 뮤티니 또는 공격에 여전히 참여할 수 있습니다. 2인용 게임에서 생략된 플레이어는 다음 순서에 대한 두 가지 동작을 모두 놓칩니다.
* 폭풍의 바다: 폭로자의 배에 있는 모든 보물은 (배에 있는 경우) 스페인 갈레온으로 돌아가거나 (토르투가에 있는 경우) 토르투가 보물은 원래의 시작 지역으로 돌아갑니다. 스페인 갈레온에 보물이 있다면, 갤레온에 있는 보물이 사라질 때까지 선장들은 서로의 배를 공격할 수 없습니다. 만약 폭로자가 보물이 없는 배에 있거나 노 젓는 배에 있다면 아무런 효과가 없습니다.
===게임 엔더 (1)===
* 스페인 아르마다: 스페인 아르마다 카드가 공개되면 게임이 끝납니다. 스페인 아르마다 카드가 마지막으로 남은 카드라면, 플레이어는 카드를 보거나 다른 플레이어에게 카드를 공개하도록 강요하는 동작을 사용하지 않을 수 있습니다.
bedb6966ed311ce3c6c53703ba8bd49c580364c0
1631
1629
2024-08-06T12:13:53Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 보물상자를 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
===모든 플레이어:===
* 1.View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 2.이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 3.다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 4.이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
1.캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
2.퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
3.캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
4.주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
==투표 카드==
위에서 부터 "공격", "싸움", 그리고 "반란"으로 카드한개에 3종류가 있습니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣을 것입니다. 각 투표 유형에 대해, 투표 덱의 맨 위 투표 카드도 추가됩니다. 그런 다음 가운데 있는 모든 카드가 섞이고 공개되며, 투표의 결과가 수행됩니다.
투표가 완료된 후, 모든 진행된 투표 카드를 투표 데크의 맨 아래에 얼굴을 아래로 향하게 섞고 배치합니다. 투표에 참여한 각 플레이어는 투표 데크의 맨 위에서 새로운 투표 카드를 뽑습니다.
====상단:공격====
배의 선장은 그들의 행동으로 공격을 요청할 수 있습니다. 선장이 배 위에 유일한 플레이어라면, 그들은 여전히 공격을 요청할 수 있습니다. 공격하는 선장의 배에 있는 플레이어들만 투표에 참여합니다.
오직 투표 카드의 맨 위 부분만이 공격에서 중요하고 대포, 횃불 또는 물을 포함합니다. 모든 물은 1개의 횃불을 취소합니다. 만약 적어도 1개의 대포가 있고, 적어도 1개의 "성공적인" 횃불이 투표에서 재생되었다면, 선장은 스페인 갤리온에서 보물 1개를 가져가서 그들의 배에 고정시킬 수 있습니다.
스페인 갤리온호가 보물을 잃어버렸다면 선장은 다른 해적선(플라잉 더치맨 또는 졸리 로저)에 보관된 보물 중 하나를 가져가서 다른 선박에 전당포가 없더라도 둘 중 하나에 보관할 수 있습니다.
예: 대포 2개, 횃불 1개, 물 1개를 재생하면 물이 횃불을 취소하고 "성공한" 횃불이 없기 때문에 공격이 실패합니다.
예: 대포 1개, 횃불 2개, 물 1개를 플레이하면 대포가 1개이고 횃불 중 1개만 물에 의해 취소되어 1개의 "성공" 횃불이 남게 되므로 공격이 성공합니다.
예: 2개의 대포와 2개의 횃불을 연주하면 공격이 성공합니다. 하지만 여전히 보물은 1개만 가져갑니다.
브롤
토르투가 주지사는 그들의 행동으로 싸움을 요청할 수 있습니다. 만약 주지사가 토르투가의 유일한 플레이어라면, 그들은 여전히 싸움을 요청할 수 있습니다. 토르투가의 플레이어들만 투표에 참여합니다.
====중단:싸움====
투표 카드의 가운데 부분만 문제가 되며 영국 국기 또는 프랑스 국기 중 하나를 포함합니다. 드러난 카드 중 다수가 영국 국기라면, 영국 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 다수가 프랑스 국기라면, 프랑스 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 동점이면, 각 지역에 하나의 보물을 배치합니다. 토르투가에 있는 두 가지 보물은 항상 토르투가에 남아 있지만, 나중에 토르투가에 있는 지역 중 하나로 옮겨질 수도 있습니다.
====하단:반란====
퍼스트 메이트(First Mate of Ship)는 반란을 행동으로 촉구할 수 있습니다. 선장을 제외한 해당 선박의 플레이어만 투표에 참여합니다.
반란은 표의 맨 아래 부분만 문제가 되고 해골이나 조타기 둘 중 하나를 포함합니다. 만약 밝혀진 카드 중 다수가 해골을 가지고 있다면, 반란을 일으키는 배의 선장은 토르투가에게 좌초됩니다. 과반수가 조타기를 가지고 있거나 동점을 가지고 있으면 아무 일도 일어나지 않습니다.
망연자실하기
배에 있는 졸개가 토르투가에 좌초되면, 같은 배의 뒤에 있는 졸개들이 빈 졸개 자리를 채우기 위해 위로 올라갑니다. 선장이 좌초되면, 1등 항해사가 선장이 됩니다. 배에 있는 모든 사람이 좌초되면, 그 배에 있는 보물은 같은 보물에 있는 그 배에 남아 있습니다. 그 보물은 게임 후반에 옮겨지지 않는 한 여전히 팀의 총 보물에 포함됩니다. 만약 플레이어가 빈 배에 탑승하면, 그들은 그 배의 선장이 됩니다.
토르투가에 정박해 있다면, 당신의 전당포는 토르투가의 선 뒤쪽에 놓이게 됩니다. 예를 들어, 만약 토르투가가 현재 비어있다면, "선의 뒤쪽"이 주지사의 위치입니다. 다른 예를 들어, 토르투가가 이미 2개의 전당포를 가지고 있다면, "선의 뒤쪽"은 "3" 위치입니다. 토르투가에 있는 동안 당신은 여전히 턴을 얻고 여전히 정상적으로 플레이어 액션을 수행할 수 있습니다.
만약 당신이 이미 토르투가에 있고 당신이 다시 석패를 당한다면, 당신에게 두 가지 일이 발생합니다. 첫째, 당신의 졸개는 토르투가의 줄 뒤쪽으로 이동되고 당신의 뒤에 순위가 매겨졌던 졸개들은 위로 올라갑니다. (만약 당신이 토르투가에 혼자 있다면 당신의 위치는 변하지 않습니다). 둘째, 당신의 투표 카드 중 하나는 다른 플레이어에 의해 무작위로 선택되고 투표 카드 덱의 맨 아래에 보이지 않게 배치됩니다. 당신은 남은 게임 동안 더 적은 수의 투표 카드로 게임을 하게 됩니다. 토르투가에 있는 동안 여러 번 석패를 당하면, 당신은 여러 투표 카드를 잃게 됩니다. 만약 당신이 투표 카드를 모두 잃는다면, 그렇게 할 수 있는 위치에 있다면 당신은 여전히 투표를 요청할 수 있지만 당신은 참여할 수 없을 것입니다.
===노 젓기 보트===
노 젓는 배로 이동하는 것은 한 가지 행동을 취합니다. 따라서 한 가지 행동으로 노 젓는 배로 이동하고 두 번째 행동으로 배나 토르투가로 이동해야 하기 때문에 토르투가에서 배로 또는 배에서 토르투가로 이동하는 데 총 두 가지 행동이 필요합니다. 현재 노 젓는 배에 전당포가 있는 경우 각 노 젓는 배에 한 번에 한 개의 전당포만 가지고 있기 때문에 다른 전당포는 그 노 젓는 배로 이동할 수 없습니다. 만약 여러분의 전당포가 노 젓는 배에 있다면 투표에 참여하지 않습니다. 다른 전당포를 차단하기 위해 노 젓는 배에 "앉아" 다른 행동(예: 카드 보기 및 공개)을 할 수 있습니다. 노 젓는 배에 타고 있다가 좌초된 경우에는 토르투가의 선 뒤쪽으로 전당포를 반납해야 하지만 투표 카드를 잃지는 않습니다.
==게임의 끝과 승리==
이벤트 덱이 다 떨어지고 공개되지 않은 이벤트 카드가 줄에 있는 5장 밖에 남지 않으면, 그 5장의 카드를 섞고 새로운 줄에 놓으세요. 스페인 아르마다 카드는 마지막 5장의 카드 중 하나가 될 것이고 공개된 카드는 더 이상 교체되지 않을 것입니다.
스페인 아르마다가 공개되면 즉시 보물이 가장 많은 팀이 게임에서 승리합니다. 게임이 끝나면 전당포가 어디에 있든 상관없이 팀과 함께 승리할 수 있습니다.
홀수 선수가 나오는 경기는 스페인 아르마다 카드가 공개됐을 때 팀이 비기면 네덜란드 선수가 이깁니다.
짝수 명의 플레이어가 있는 게임에서 스페인 아르마다 카드가 공개되었을 때 팀이 동점이 되면 게임에서 스페인 아르마다 카드를 제거하고 버려지고 공개되지 않은 모든 이벤트 카드를 새로운 이벤트 덱에 섞습니다. 알바트로스, 레터 오브 마르케 또는 보물 지도와 같이 현재 플레이어 앞에 있는 카드를 섞지 마십시오. 연속으로 5개의 새로운 이벤트 카드를 배치하고 중단한 곳에서 계속 플레이하십시오. 주도권을 잡은 첫 번째 팀이 게임에서 이깁니다.
==이벤트 카드==
아래 설명에서 모든 플레이어는 자신을 포함합니다. 다른 플레이어는 자신을 포함하지 않습니다. 모든 카드 해상도는 공개 시 필수입니다.
====유용한 카드(6)====
* 마크의 편지 (3): 드러버는 토르투가나 노 젓는 배에 있는 모든 플레이어를 두 배의 라인 뒤쪽으로 이동시킵니다. 드러버는 또한 이 카드를 저장하고 미래의 행동으로 사용할 수 있습니다.
* 권총 (3): 폭로자가 다른 플레이어를 선택합니다. 그 플레이어는 낙오되었습니다. 권총은 나중의 액션으로 사용하기 위해 저장할 수 없습니다.
====상처를 주는 카드(6)====
* 알바트로스 (3): 폭로자는 게임의 나머지 기간 동안 이 카드를 그들 앞에 얼굴을 비추게 합니다. 만약 어떤 시점에서 배에 총 2개의 알바트로스가 있다면, 그 배에 있는 모든 플레이어는 토르투가에 버려집니다. 예: 게임 초반에 일등 항해사가 알바트로스를 공개하고 그들 앞에 그것을 가지고 있습니다. 만약 그 일등 항해사의 배에 있는 누군가 (자신들을 포함하여) 또 다른 알바트로스를 공개하면, 그 배에 있는 모든 플레이어(심지어 알바트로스 카드가 없는 플레이어도)는 토르투가에 버려집니다. 만약 당신이 알바트로스 카드 2개를 가지고 배에 들어가면, 배에 있는 모든 사람(방금 배에 가입한 당신을 포함하여)은 즉시 토르투가에 버려집니다. 당신은 본질적으로 걷는 폭탄입니다. 알바트로스 카드는 토르투가에 아무런 영향을 미치지 않습니다. 만약 둘 이상의 플레이어가 알바트로스 카드에 빠져 동시에 토르투가에 들어오면, 그들은 순위를 뒤집습니다 (캐빈 보이는 토르투가에서 최고 순위의 오픈 폰 자리를 얻게 되고, 캡틴은 최악이 됩니다 등).
* Black Spot (3): Rebeller가 잠겼습니다.
====TREASURE MAPS (3)====
폭로자는 보물 지도를 다른 플레이어에게 줍니다. 카드가 주어진 플레이어가 보물 지도를 사용할 때, 그것은 액션으로 간주되지 않습니다. 플레이어는 여러 개의 보물 지도를 받고 소유할 수 있습니다. 2인용 및 3인용 게임에서 플레이어는 여전히 드러난 보물 지도를 다른 플레이어에게 주어야 합니다.
* 아틀란티스 (1): 소유자는 플레이어의 차례 직전에 한 배에서 다른 배의 라인 뒤쪽으로 이동할 수 있습니다 (자신의 차례 포함). 아틀란티스를 사용하는 것은 행동으로 간주되지 않습니다. 소유자는 토르투가나 노 젓는 배에서 배로 이동하기 위해 이 카드를 사용할 수 없습니다. 사용 후 폐기하십시오.
* 엘도라도 (1): 소유자는 즉시 투표 카드를 한 장 더 뽑습니다. 앞으로 있을 투표에서, 소유자는 보통 투표 카드 대신 두 장의 투표 카드를 사용할 수 있습니다. 엘도라도 (토투가에서 투표 카드가 잠기는 것을 줄여주는 사람들을 포함하여) 주어진 플레이어는 엘도라도 카드를 가지고 더 많은 투표 카드를 손에 유지하기 위해 그 능력을 사용하지 않을 수 있습니다. 투표에서 두 장의 카드를 사용한 후 엘도라도 카드를 버리세요.
* 젊음의 샘 (1): 소유자는 흑점을 드러내거나 권총으로 총을 맞거나 선장에게 유괴되거나 반란에 성공한 후 유괴되지 않기로 선택할 수 있습니다. 사용 후 폐기하십시오.
====스타드 카드 (각 게임에 무작위로 3개 추가)====
* 검은 가루: 폭로자는 폭발 토큰을 노 젓는 배에 놓습니다. 그 노 젓는 배는 게임의 나머지 부분에 사용되지 않을 수도 있습니다. 만약 플레이어가 현재 그 노 젓는 배에 있다면, 그들은 토르투가의 선 뒤쪽에 정박하게 됩니다. 노 젓는 배 없이 배로 이동하는 유일한 방법은 마르케 또는 아틀란티스의 편지를 사용하는 것입니다.
* 캐빈 피버: 폭로자가 다른 플레이어 1명을 선택합니다. 폭로자와 선택한 플레이어의 충성 카드는 뒤섞여 각각에게 재배포됩니다. 그들은 각각 비밀리에 새로운 충성 카드를 봅니다.
* 까마귀 둥지: 폭로자는 투표 데크에 한 플레이어의 투표 카드 손을 아래로 향하게 배치합니다. 그런 다음 폭로자는 개인적으로 해당 플레이어의 손에 있던 카드를 대체할 전체 투표 데크를 검색합니다. 완료 후 투표 데크를 섞습니다. 까마귀 둥지가 공개되었을 때 가지고 있던 것과 동일한 수의 투표 카드로 해당 플레이어의 손을 교체해야 합니다.
* 여덟 개의 종: 폭로자의 배나 섬에 있는 모든 졸개들은 주머니에 넣어지고 무작위로 그 배나 섬으로 다시 꺼내집니다. 폭로자가 혼자 있거나 노 젓는 배에 있으면 효과가 없습니다.
* 파사드: 폭로자는 오른쪽에 앉은 플레이어와 폰 위치를 바꿉니다.
* 해적 코드: 폭로자는 자신들이 속해 있었을 다음 두 표 (공격, 반란, 또는 싸움)에 참여하지 않을 수 있습니다. 만약 그렇게 할 수 있는 위치에 있다면 그들은 여전히 투표를 요청할 수 있습니다. 만약 그들이 투표를 위해 혼자 있다면, 투표 카드는 여전히 갑판에서 추가됩니다. 두 번째 투표에 참여하지 않은 후 폐기하세요.
* Scurvy: 폭로자를 포함하여 폭로자와 같은 배 또는 섬에 있는 모든 플레이어는 다음 순서를 잃습니다. 그 플레이어는 Scurvy 폭로자의 배 또는 섬에서 이동하더라도 여전히 다음 순서를 잃습니다. 순서를 잃는 플레이어는 스킵되지 않은 플레이어가 요청한 관련 싸움, 뮤티니 또는 공격에 여전히 참여할 수 있습니다. 2인용 게임에서 생략된 플레이어는 다음 순서에 대한 두 가지 동작을 모두 놓칩니다.
* 폭풍의 바다: 폭로자의 배에 있는 모든 보물은 (배에 있는 경우) 스페인 갈레온으로 돌아가거나 (토르투가에 있는 경우) 토르투가 보물은 원래의 시작 지역으로 돌아갑니다. 스페인 갈레온에 보물이 있다면, 갤레온에 있는 보물이 사라질 때까지 선장들은 서로의 배를 공격할 수 없습니다. 만약 폭로자가 보물이 없는 배에 있거나 노 젓는 배에 있다면 아무런 효과가 없습니다.
===게임 엔더 (1)===
* 스페인 아르마다: 스페인 아르마다 카드가 공개되면 게임이 끝납니다. 스페인 아르마다 카드가 마지막으로 남은 카드라면, 플레이어는 카드를 보거나 다른 플레이어에게 카드를 공개하도록 강요하는 동작을 사용하지 않을 수 있습니다.
600d840a5ee56f94f7b2791bbe9f2e646f319b3f
1632
1631
2024-08-06T12:49:04Z
Moonyo
7890
wikitext
text/x-wiki
==요약==
선수들은 균등하게 (영국, 프랑스) 팀으로 나뉘며, 홀수 명일 경우 네덜란드 선수는 1명이 됩니다. 어느 쪽이든, 소속팀은 비밀이고, 다른 선수들에게 소속팀을 공개하지 않을 수 있습니다
이 후, 플레이어는 두 보트에 무작위로 배포됩니다.
설정을 마치기 위해, 각 배의 선장은 그들의 배를 위한 첫 번째 보물을 어느 국적으로 보유할지를 결정합니다
우승팀은 스페인 아르마다 이벤트 카드가 공개될 때 팀 홀드에서 가장 많은 보물상자를 가진 팀입니다. 네덜란드 팀은 경기가 끝날 때 영국과 프랑스 팀이 비길 때만 이깁니다. 만약 네덜란드 팀이 없다면 스페인 아르마다를 제거하고 이벤트 덱을 갈아서 더 이상 비기지 않을 때까지 경기를 계속합니다.
==조건.==
* 선장: 두 배의 맨 앞에 있는 사람.
* 퍼스트 메이트: 어느 배의 두 번째 공간에 있는 사람.
* 캐빈 보이: 배의 마지막 사람입니다. 이 사람은 일등 항해사일 수도 있고 혼자라면 선장일 수도 있습니다.
* 주지사: 토르투가에 줄을 선 첫 번째 사람입니다.
==행동==
순서에 따라 수행할 수 있는 여러 가지 액션이 있으며 캐릭터의 위치에 따라 액션이 달라집니다. 참고: 2인 게임에서는 각 플레이어가 한 순서에 2개의 액션을 얻습니다.
===모든 플레이어:===
* 1.View 2 Event Cards(이벤트 카드 보기): Face-Down Event Cards(페이스다운) 5장 중 2장 중 2장은 비밀리에 보기
* 2.이벤트 카드 1장 공개: 이벤트 카드 중 하나를 공개합니다. 이 카드를 모든 플레이어에게 보여주고 카드에 나열된 결과를 해결합니다. 공개된 카드를 이벤트 덱의 맨 위 카드로 얼굴을 아래로 향하게 교체합니다
* 3.다른 플레이어가 두 개의 이벤트 카드 중 하나를 공개하도록 강제합니다. 다른 플레이어를 선택한 다음 이벤트 카드 중 2개를 선택합니다. 선택한 플레이어가 두 개의 이벤트 카드 중 하나를 선택하여 모든 플레이어에게 공개하고 해결합니다
* 4.이동: 여러분의 졸개를 배나 토르투가에서 인접한 노 젓는 배로 이동시키세요. 또는, 여러분의 졸개를 노 젓는 배에서 토르투가의 선 뒤쪽 또는 인접한 배의 선 뒤쪽으로 이동시키세요
1.캡틴:
* 공격 요청: 성공적인 공격은 스페인 갤리온에서 보물을 가져가게 해줍니다. 만약 스페인 갤리온이 보물을 잃어버렸다면, 성공적인 공격은 다른 해적선으로부터 보물을 가져가게 해줍니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
* 플레이어 마룬: 토르투가로 가는 배에 있는 다른 졸개를 마룬합니다
2.퍼스트 메이트:
* 반란을 불러라: 성공적인 반란은 당신의 대장을 토르투가로 침몰시킵니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
3.캐빈 보이:
* 보물 이동: 배 위에 이미 있는 보물 토큰 1개를 영국 보물 창고에서 프랑스 보물 창고로 옮기거나, 그 반대의 경우도 마찬가지입니다
4.주지사:
* 싸움 부르기: 싸움은 토르투가에 있는 보물 2개를 토르투가에 있는 보물 구역 중 하나 또는 둘 다로 옮깁니다. 자세한 내용은 "투표 카드" 섹션을 참조하십시오
==투표 카드==
위에서 부터 "공격", "싸움", 그리고 "반란"으로 카드한개에 3종류가 있습니다. 투표가 요청되면, 투표에 참여하는 모든 플레이어는 그들의 투표 카드 중 하나를 가운데에 넣을 것입니다. 각 투표 유형에 대해, 투표 덱의 맨 위 투표 카드도 추가됩니다. 그런 다음 가운데 있는 모든 카드가 섞이고 공개되며, 투표의 결과가 수행됩니다.
투표가 완료된 후, 모든 진행된 투표 카드를 투표 데크의 맨 아래에 얼굴을 아래로 향하게 섞고 배치합니다. 투표에 참여한 각 플레이어는 투표 데크의 맨 위에서 새로운 투표 카드를 뽑습니다.
====상단:공격====
배의 선장은 그들의 행동으로 공격을 요청할 수 있습니다. 선장이 배 위에 유일한 플레이어라면, 그들은 여전히 공격을 요청할 수 있습니다. 공격하는 선장의 배에 있는 플레이어들만 투표에 참여합니다.
오직 투표 카드의 맨 위 부분만이 공격에서 중요하고 대포, 횃불 또는 물을 포함합니다. 모든 물은 1개의 횃불을 취소합니다. 만약 적어도 1개의 대포가 있고, 적어도 1개의 "성공적인" 횃불이 투표에서 재생되었다면, 선장은 스페인 갤리온에서 보물 1개를 가져가서 그들의 배에 고정시킬 수 있습니다.
스페인 갤리온호가 보물을 잃어버렸다면 선장은 다른 해적선(플라잉 더치맨 또는 졸리 로저)에 보관된 보물 중 하나를 가져가서 다른 선박에 전당포가 없더라도 둘 중 하나에 보관할 수 있습니다.
예: 대포 2개, 횃불 1개, 물 1개를 재생하면 물이 횃불을 취소하고 "성공한" 횃불이 없기 때문에 공격이 실패합니다.
예: 대포 1개, 횃불 2개, 물 1개를 플레이하면 대포가 1개이고 횃불 중 1개만 물에 의해 취소되어 1개의 "성공" 횃불이 남게 되므로 공격이 성공합니다.
예: 2개의 대포와 2개의 횃불을 연주하면 공격이 성공합니다. 하지만 여전히 보물은 1개만 가져갑니다.
브롤
토르투가 주지사는 그들의 행동으로 싸움을 요청할 수 있습니다. 만약 주지사가 토르투가의 유일한 플레이어라면, 그들은 여전히 싸움을 요청할 수 있습니다. 토르투가의 플레이어들만 투표에 참여합니다.
====중단:싸움====
투표 카드의 가운데 부분만 문제가 되며 영국 국기 또는 프랑스 국기 중 하나를 포함합니다. 드러난 카드 중 다수가 영국 국기라면, 영국 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 다수가 프랑스 국기라면, 프랑스 보물 지역의 토르투가에 두 가지 보물을 배치하십시오. 동점이면, 각 지역에 하나의 보물을 배치합니다. 토르투가에 있는 두 가지 보물은 항상 토르투가에 남아 있지만, 나중에 토르투가에 있는 지역 중 하나로 옮겨질 수도 있습니다.
====하단:반란====
퍼스트 메이트(First Mate of Ship)는 반란을 행동으로 촉구할 수 있습니다. 선장을 제외한 해당 선박의 플레이어만 투표에 참여합니다.
반란은 표의 맨 아래 부분만 문제가 되고 해골이나 조타기 둘 중 하나를 포함합니다. 만약 밝혀진 카드 중 다수가 해골을 가지고 있다면, 반란을 일으키는 배의 선장은 토르투가에게 좌초됩니다. 과반수가 조타기를 가지고 있거나 동점을 가지고 있으면 아무 일도 일어나지 않습니다.
망연자실하기
배에 있는 졸개가 토르투가에 좌초되면, 같은 배의 뒤에 있는 졸개들이 빈 졸개 자리를 채우기 위해 위로 올라갑니다. 선장이 좌초되면, 1등 항해사가 선장이 됩니다. 배에 있는 모든 사람이 좌초되면, 그 배에 있는 보물은 같은 보물에 있는 그 배에 남아 있습니다. 그 보물은 게임 후반에 옮겨지지 않는 한 여전히 팀의 총 보물에 포함됩니다. 만약 플레이어가 빈 배에 탑승하면, 그들은 그 배의 선장이 됩니다.
토르투가에 정박해 있다면, 당신의 전당포는 토르투가의 선 뒤쪽에 놓이게 됩니다. 예를 들어, 만약 토르투가가 현재 비어있다면, "선의 뒤쪽"이 주지사의 위치입니다. 다른 예를 들어, 토르투가가 이미 2개의 전당포를 가지고 있다면, "선의 뒤쪽"은 "3" 위치입니다. 토르투가에 있는 동안 당신은 여전히 턴을 얻고 여전히 정상적으로 플레이어 액션을 수행할 수 있습니다.
만약 당신이 이미 토르투가에 있고 당신이 다시 석패를 당한다면, 당신에게 두 가지 일이 발생합니다. 첫째, 당신의 졸개는 토르투가의 줄 뒤쪽으로 이동되고 당신의 뒤에 순위가 매겨졌던 졸개들은 위로 올라갑니다. (만약 당신이 토르투가에 혼자 있다면 당신의 위치는 변하지 않습니다). 둘째, 당신의 투표 카드 중 하나는 다른 플레이어에 의해 무작위로 선택되고 투표 카드 덱의 맨 아래에 보이지 않게 배치됩니다. 당신은 남은 게임 동안 더 적은 수의 투표 카드로 게임을 하게 됩니다. 토르투가에 있는 동안 여러 번 석패를 당하면, 당신은 여러 투표 카드를 잃게 됩니다. 만약 당신이 투표 카드를 모두 잃는다면, 그렇게 할 수 있는 위치에 있다면 당신은 여전히 투표를 요청할 수 있지만 당신은 참여할 수 없을 것입니다.
===TIP.노 젓기 보트===
노 젓는 배로 이동하는 것은 한 가지 행동을 취합니다. 따라서 한 가지 행동으로 노 젓는 배로 이동하고 두 번째 행동으로 배나 토르투가로 이동해야 하기 때문에 토르투가에서 배로 또는 배에서 토르투가로 이동하는 데 총 두 가지 행동이 필요합니다. 현재 노 젓는 배에 전당포가 있는 경우 각 노 젓는 배에 한 번에 한 개의 전당포만 가지고 있기 때문에 다른 전당포는 그 노 젓는 배로 이동할 수 없습니다. 만약 여러분의 전당포가 노 젓는 배에 있다면 투표에 참여하지 않습니다. 다른 전당포를 차단하기 위해 노 젓는 배에 "앉아" 다른 행동(예: 카드 보기 및 공개)을 할 수 있습니다. 노 젓는 배에 타고 있다가 좌초된 경우에는 토르투가의 선 뒤쪽으로 전당포를 반납해야 하지만 투표 카드를 잃지는 않습니다.
==게임의 끝과 승리==
이벤트 덱이 다 떨어지고 공개되지 않은 이벤트 카드가 줄에 있는 5장 밖에 남지 않으면, 그 5장의 카드를 섞고 새로운 줄에 놓으세요. 스페인 아르마다 카드는 마지막 5장의 카드 중 하나가 될 것이고 공개된 카드는 더 이상 교체되지 않을 것입니다.
스페인 아르마다가 공개되면 즉시 보물이 가장 많은 팀이 게임에서 승리합니다. 게임이 끝나면 전당포가 어디에 있든 상관없이 팀과 함께 승리할 수 있습니다.
홀수 선수가 나오는 경기는 스페인 아르마다 카드가 공개됐을 때 팀이 비기면 네덜란드 선수가 이깁니다.
짝수 명의 플레이어가 있는 게임에서 스페인 아르마다 카드가 공개되었을 때 팀이 동점이 되면 게임에서 스페인 아르마다 카드를 제거하고 버려지고 공개되지 않은 모든 이벤트 카드를 새로운 이벤트 덱에 섞습니다. 알바트로스, 레터 오브 마르케 또는 보물 지도와 같이 현재 플레이어 앞에 있는 카드를 섞지 마십시오. 연속으로 5개의 새로운 이벤트 카드를 배치하고 중단한 곳에서 계속 플레이하십시오. 주도권을 잡은 첫 번째 팀이 게임에서 이깁니다.
==이벤트 카드==
아래 설명에서 모든 플레이어는 자신을 포함합니다. 다른 플레이어는 자신을 포함하지 않습니다. 모든 카드 해상도는 공개 시 필수입니다.
====유용한 카드(6)====
* 마크의 편지 (3): 드러버는 토르투가나 노 젓는 배에 있는 모든 플레이어를 두 배의 라인 뒤쪽으로 이동시킵니다. 드러버는 또한 이 카드를 저장하고 미래의 행동으로 사용할 수 있습니다.
* 권총 (3): 폭로자가 다른 플레이어를 선택합니다. 그 플레이어는 낙오되었습니다. 권총은 나중의 액션으로 사용하기 위해 저장할 수 없습니다.
====상처를 주는 카드(6)====
* 알바트로스 (3): 폭로자는 게임의 나머지 기간 동안 이 카드를 그들 앞에 얼굴을 비추게 합니다. 만약 어떤 시점에서 배에 총 2개의 알바트로스가 있다면, 그 배에 있는 모든 플레이어는 토르투가에 버려집니다. 예: 게임 초반에 일등 항해사가 알바트로스를 공개하고 그들 앞에 그것을 가지고 있습니다. 만약 그 일등 항해사의 배에 있는 누군가 (자신들을 포함하여) 또 다른 알바트로스를 공개하면, 그 배에 있는 모든 플레이어(심지어 알바트로스 카드가 없는 플레이어도)는 토르투가에 버려집니다. 만약 당신이 알바트로스 카드 2개를 가지고 배에 들어가면, 배에 있는 모든 사람(방금 배에 가입한 당신을 포함하여)은 즉시 토르투가에 버려집니다. 당신은 본질적으로 걷는 폭탄입니다. 알바트로스 카드는 토르투가에 아무런 영향을 미치지 않습니다. 만약 둘 이상의 플레이어가 알바트로스 카드에 빠져 동시에 토르투가에 들어오면, 그들은 순위를 뒤집습니다 (캐빈 보이는 토르투가에서 최고 순위의 오픈 폰 자리를 얻게 되고, 캡틴은 최악이 됩니다 등).
* Black Spot (3): Rebeller가 잠겼습니다.
====TREASURE MAPS (3)====
폭로자는 보물 지도를 다른 플레이어에게 줍니다. 카드가 주어진 플레이어가 보물 지도를 사용할 때, 그것은 액션으로 간주되지 않습니다. 플레이어는 여러 개의 보물 지도를 받고 소유할 수 있습니다. 2인용 및 3인용 게임에서 플레이어는 여전히 드러난 보물 지도를 다른 플레이어에게 주어야 합니다.
* 아틀란티스 (1): 소유자는 플레이어의 차례 직전에 한 배에서 다른 배의 라인 뒤쪽으로 이동할 수 있습니다 (자신의 차례 포함). 아틀란티스를 사용하는 것은 행동으로 간주되지 않습니다. 소유자는 토르투가나 노 젓는 배에서 배로 이동하기 위해 이 카드를 사용할 수 없습니다. 사용 후 폐기하십시오.
* 엘도라도 (1): 소유자는 즉시 투표 카드를 한 장 더 뽑습니다. 앞으로 있을 투표에서, 소유자는 보통 투표 카드 대신 두 장의 투표 카드를 사용할 수 있습니다. 엘도라도 (토투가에서 투표 카드가 잠기는 것을 줄여주는 사람들을 포함하여) 주어진 플레이어는 엘도라도 카드를 가지고 더 많은 투표 카드를 손에 유지하기 위해 그 능력을 사용하지 않을 수 있습니다. 투표에서 두 장의 카드를 사용한 후 엘도라도 카드를 버리세요.
* 젊음의 샘 (1): 소유자는 흑점을 드러내거나 권총으로 총을 맞거나 선장에게 유괴되거나 반란에 성공한 후 유괴되지 않기로 선택할 수 있습니다. 사용 후 폐기하십시오.
====스타드 카드 (각 게임에 무작위로 3개 추가)====
* 검은 가루: 폭로자는 폭발 토큰을 노 젓는 배에 놓습니다. 그 노 젓는 배는 게임의 나머지 부분에 사용되지 않을 수도 있습니다. 만약 플레이어가 현재 그 노 젓는 배에 있다면, 그들은 토르투가의 선 뒤쪽에 정박하게 됩니다. 노 젓는 배 없이 배로 이동하는 유일한 방법은 마르케 또는 아틀란티스의 편지를 사용하는 것입니다.
* 캐빈 피버: 폭로자가 다른 플레이어 1명을 선택합니다. 폭로자와 선택한 플레이어의 충성 카드는 뒤섞여 각각에게 재배포됩니다. 그들은 각각 비밀리에 새로운 충성 카드를 봅니다.
* 까마귀 둥지: 폭로자는 투표 데크에 한 플레이어의 투표 카드 손을 아래로 향하게 배치합니다. 그런 다음 폭로자는 개인적으로 해당 플레이어의 손에 있던 카드를 대체할 전체 투표 데크를 검색합니다. 완료 후 투표 데크를 섞습니다. 까마귀 둥지가 공개되었을 때 가지고 있던 것과 동일한 수의 투표 카드로 해당 플레이어의 손을 교체해야 합니다.
* 여덟 개의 종: 폭로자의 배나 섬에 있는 모든 졸개들은 주머니에 넣어지고 무작위로 그 배나 섬으로 다시 꺼내집니다. 폭로자가 혼자 있거나 노 젓는 배에 있으면 효과가 없습니다.
* 파사드: 폭로자는 오른쪽에 앉은 플레이어와 폰 위치를 바꿉니다.
* 해적 코드: 폭로자는 자신들이 속해 있었을 다음 두 표 (공격, 반란, 또는 싸움)에 참여하지 않을 수 있습니다. 만약 그렇게 할 수 있는 위치에 있다면 그들은 여전히 투표를 요청할 수 있습니다. 만약 그들이 투표를 위해 혼자 있다면, 투표 카드는 여전히 갑판에서 추가됩니다. 두 번째 투표에 참여하지 않은 후 폐기하세요.
* Scurvy: 폭로자를 포함하여 폭로자와 같은 배 또는 섬에 있는 모든 플레이어는 다음 순서를 잃습니다. 그 플레이어는 Scurvy 폭로자의 배 또는 섬에서 이동하더라도 여전히 다음 순서를 잃습니다. 순서를 잃는 플레이어는 스킵되지 않은 플레이어가 요청한 관련 싸움, 뮤티니 또는 공격에 여전히 참여할 수 있습니다. 2인용 게임에서 생략된 플레이어는 다음 순서에 대한 두 가지 동작을 모두 놓칩니다.
* 폭풍의 바다: 폭로자의 배에 있는 모든 보물은 (배에 있는 경우) 스페인 갈레온으로 돌아가거나 (토르투가에 있는 경우) 토르투가 보물은 원래의 시작 지역으로 돌아갑니다. 스페인 갈레온에 보물이 있다면, 갤레온에 있는 보물이 사라질 때까지 선장들은 서로의 배를 공격할 수 없습니다. 만약 폭로자가 보물이 없는 배에 있거나 노 젓는 배에 있다면 아무런 효과가 없습니다.
===게임 끝 (1)===
* 스페인 아르마다: 스페인 아르마다 카드가 공개되면 게임이 끝납니다. 스페인 아르마다 카드가 마지막으로 남은 카드라면, 플레이어는 카드를 보거나 다른 플레이어에게 카드를 공개하도록 강요하는 동작을 사용하지 않을 수 있습니다.
78524b046e37ac65adc88ac960e708d172b7382f
Gamehelpmojo
0
285
1614
1592
2024-06-22T13:54:15Z
Moonyo
7890
wikitext
text/x-wiki
===요약===
가장 적은 포인트를 얻은 플레이어가 승리합니다
===준비===
각 플레이어는 8장의 카드를 핸드로 가져갑니다.
시작 플레이어부터 모조 카드에 나와있는 방향대로 카드를 내며 순서를 진행합니다.
===방법===
1. 플레이 하는 숫자 카드가 중앙에 놓여진 카드보다 큰 숫자의 경우, 카드를 한 장 받습니다.
2. 같은 숫자의 카드를 낸 경우, 즉시 다른 카드 한 장을 더 냅니다.
3. 플레이어의 손에 들고있는 카드가 3장 이하가 된 경우, 모조 타임이 시작됩니다.
모조타임을 시작한 플레이어는 남은 카드를 뒷면으로 놓고 자신의 차례마다 차례를 진행하는 대신 남은 카드를 한 장씩 뒤집습니다.
모조타임을 시작하지 않은 플레이어는 차례가 될 때마다 모조타임을 시작한 플레이어의 카드가 모두 윗면을 향할 때 까지 계속해서 플레이 합니다.
(2인 경기에는 카드가 2장이 된 경우 모조타임이 발동됩니다)
4. 모조타임이 끝나면 남아있는 카드에 적힌 숫자를 합산하여 누가 가장 적은지 비교합니다.
이때, 만약 모조타임을 시작한 플레이어가 가장 적은 숫자가라면, 모조 카드를 +0면으로 가져가고 0점을 획득합니다.
반대의 경우, 패널티로 모조 카드를 +10 면으로 뒤집어 자신의 포인트에 10점을 추가합니다.
===규칙===
<nowiki/>: 모조타임이 끝나고 손에 남은 카드를 비교할 때 같은 색깔 카드가 여러장 있다면, 그 색깔 그룹의 가장 높은 숫자 카드 한 장만 숫자를 확인합니다.
만약 같은 숫자가 여러개라면, 숫자가 하나만 있는것으로 취급합니다.
===카드 종류 및 갯수===
파란색 (0-1) - 4장씩
초록색 (2-4) - 5장씩
노란색 (5-7) - 6장씩
주황색 (8-10) - 7장씩
빨간색 (11-12) - 8장씩
가장 적은 포인트를 얻어 게임에서 승리하세요!
8afb8c4dc5fad2744f281bb253659de1aee4a9bb
1615
1614
2024-06-22T14:04:05Z
Moonyo
7890
wikitext
text/x-wiki
===요약===
가장 적은 포인트를 얻은 플레이어가 승리합니다
===준비===
각 플레이어는 8장의 카드를 핸드로 가져갑니다.
시작 플레이어부터 모조 카드에 나와있는 방향대로 카드를 내며 순서를 진행합니다.
===방법===
1. 플레이 하는 숫자 카드가 중앙에 놓여진 카드보다 큰 숫자의 경우, 카드를 한 장 받습니다.
2. 같은 숫자의 카드를 낸 경우, 즉시 다른 카드 한 장을 더 냅니다.
3. 플레이어의 손에 들고있는 카드가 3장 이하가 된 경우, 모조 타임이 시작됩니다.
모조타임을 시작한 플레이어는 남은 카드를 뒷면으로 놓고 자신의 차례마다 차례를 진행하는 대신 남은 카드를 한 장씩 뒤집습니다.
모조타임을 시작하지 않은 플레이어는 차례가 될 때마다 모조타임을 시작한 플레이어의 카드가 모두 윗면을 향할 때 까지 계속해서 플레이 합니다.
(2인 경기에는 카드가 2장이 된 경우 모조타임이 발동됩니다)
4. 모조타임이 끝나면 남아있는 카드에 적힌 숫자를 합산하여 누가 가장 적은지 비교합니다.
이때, 만약 모조타임을 시작한 플레이어가 가장 적은 숫자가라면, 모조 카드를 +0면으로 가져가고 0점을 획득합니다.
반대의 경우, 패널티로 모조 카드를 +10 면으로 뒤집어 자신의 포인트에 10점을 추가합니다.
===규칙===
<nowiki/>: 모조타임이 끝나고 손에 남은 카드를 비교할 때 같은 색깔 카드가 여러장 있다면, 그 색깔 그룹의 가장 높은 숫자 카드 한 장만 숫자를 확인합니다.
만약 같은 숫자가 여러개라면, 숫자가 하나만 있는것으로 취급합니다.
===카드 종류 및 갯수===
파란색 (0-1) - 4장씩
초록색 (2-4) - 5장씩
노란색 (5-7) - 6장씩
주황색 (8-10) - 7장씩
빨간색 (11-12) - 8장씩
가장 적은 포인트를 얻어 게임에서 승리하세요!
27ba3da057010306623cb263e39a51e7de4c946b
Gamehelpwarchest
0
294
1616
2024-06-26T12:21:23Z
Joonseok Kim
9884
새 문서: == 개요 == 이 게임의 목적은 먼저 자신의 점령 마커 6개를 초록색 칸(거점)에 놓는 것입니다. 게임을 시작할 때 두 개의 거점을 점령한 상태로 시작합니다. 각 플레이어는 서로 다른 유닛 토큰을 갖고 게임을 진행하게 됩니다. 각 유닛의 특별 행동은 모두 다릅니다. == 주요 규칙 == 보드판 위에는 같은 종류의 유닛 토큰(더미)은 동시에 두 군데 이상 놓일 수 없습니다....
wikitext
text/x-wiki
== 개요 ==
이 게임의 목적은 먼저 자신의 점령 마커 6개를 초록색 칸(거점)에 놓는 것입니다. 게임을 시작할 때 두 개의 거점을 점령한 상태로 시작합니다. 각 플레이어는 서로 다른 유닛 토큰을 갖고 게임을 진행하게 됩니다. 각 유닛의 특별 행동은 모두 다릅니다.
== 주요 규칙 ==
보드판 위에는 같은 종류의 유닛 토큰(더미)은 동시에 두 군데 이상 놓일 수 없습니다.
코인은
ed8888039d42a796b9f993ce266ee1874b2684be
1617
1616
2024-06-26T14:06:19Z
Joonseok Kim
9884
wikitext
text/x-wiki
== 개요 ==
이 게임의 목적은 보드판 위의 거점(초록색 칸) 중 6개를 점령한 상태에 먼저 도달하는 것입니다.
게임을 시작할 때 각 플레이어는 두 개의 거점을 점령한 상태로 시작합니다.
플레이어는 서로 다른 속성을 갖는 유닛을 가지고 게임을 진행하게 됩니다.
== 주요 규칙 ==
보드판 위에는 같은 종류의 유닛 코인(더미)이 동시에 두 군데 이상 놓일 수 없습니다.
보드판 위에 있는 것과 같은 종류의 코인을 앞면으로 사용하면서 보드판 위의 코인을 행동할 수 있습니다.
각 플레이어들은 국왕 코인을 하나씩 갖는데 대개 뒷면으로만 사용 가능하며, 특수한 유닛 전술에 의해 사용되거나 노빌리티 확장에서 칙령을 선포하는 데에 사용되기도 합니다.
플레이어들은 코인을 하나씩 사용하면서 번갈아 가며 차례를 진행하고, 꺼내놓은 코인이 하나도 남지 않았을 때 주머니에서 새로 3개의 코인을 보지 않고 꺼냅니다.
== 턴 진행 ==
자신의 차례에는 꺼내놓은 코인 하나를 선택하여 보드판에 배치하거나 앞면 또는 뒷면으로 버립니다.
=== 배치 ===
코인을 보드판에 배치하기로 선택했다면 자신이 점령하고 있는 비어 있는 거점에 투입하거나, 이미 같은 유닛이 있는 칸에 올려 증원합니다.(증원은 적으로 하여금 해당 유닛을 제거하기 더 어렵게 만듭니다.)
=== 뒷면 버리기 ===
다음 3가지 행동 중 선택합니다.
- 현재 선공 토큰을 가지고 있지 않다면, 다음 라운드의 선공을 선언할 수 있습니다.
- 현재 차례를 건너 뜁니다.(코인 하나는 버리지만, 해당 라운드의 남은 차례는 다시 돌아오게 됩니다.)
- 공급처로부터 코인 하나를 모집하여 버린 영역에 놓습니다. 어떤 유닛을 모집했는지 상대방이 알 수 있도록 앞면으로 공개해 두어야 합니다.
=== 앞면 버리기 ===
버리는 코인과 동일한 유닛을 골라 다음 4가지 작전 중 하나를 선택합니다.
- 인접한 빈 칸으로 코인(더미)을 이동합니다.
- 거점을 점령합니다. 해당 유닛이 현재 위치한 칸에 자신의 점령 마커를 올립니다. 상대의 마커이 있는 경우 거점 밖으로 되돌려 놓고 자신의 마커를 올려두면 됩니다.
- 인접한 적 유닛을 공격합니다. 공격받은 적 유닛은 코인을 게임에서 완전히 제거합니다. 코인이 2개 이상 더미로 쌓여있는 경우에는 하나가 제거되더라도 나머지 코인은 해당 칸에 남아있게 됩니다.
- 유닛의 전술을 활성화합니다. 전술은 각 유닛의 고유 능력으로 유닛 카드에 적혀있습니다. ! 표시는 기본 규칙에 추가되는 능력을 뜻하며, X 표시는 기본 규칙에 제약이 있음을 의미합니다.
=== 기본 규칙 끝 ===
상급 규칙이나 4인 플레이 규칙이 필요하면 아래를 더 보시면 됩니다.
== 상급 규칙 ==
== 4인 플레이(팀 대결) ==
- 각 팀은 시작 시 3개의 거점을 점령한 상태로 시작합니다.
- 각 플레이어들은 3가지 유닛으로 게임을 진행합니다.
- 선공 마커를 가지고 있는 플레이어와 같은 팀인 플레이어는 선공을 가져오는 행동을 할 수 없습니다.
- 두 팀간 플레이어들이 교차로 순서를 진행합니다.
- 점령 마커는 팀원 간에 공유됩니다.(같은 팀원이 점령한 칸은 해당 팀의 점령 칸으로 취급합니다.)
- 모집 행동은 자신의 유닛만 모집할 수 있으며, 팀의 유닛을 대신 모집할 수는 없습니다.
- 같은 팀의 플레이어끼리는 아군 관계입니다. 같은 팀원에 피해를 입힐 수 없습니다.
- 전술로 아군의 유닛이 행동할 수 있는 경우, 같은 팀의 플레이어의 유닛을 행동하게 하는 것도 가능합니다.
- 비밀 토론은 불가하며, 전략적인 상의를 포함한 어떠한 대화도 다른 팀 앞에서 공개적으로 해야 합니다.
2c84b57141ea9b22e7239d75cdd81bf57f0a4506
1618
1617
2024-06-26T14:07:29Z
Joonseok Kim
9884
wikitext
text/x-wiki
== 개요 ==
이 게임의 목적은 보드판 위의 거점(초록색 칸) 중 6개를 점령한 상태에 먼저 도달하는 것입니다.
게임을 시작할 때 각 플레이어는 두 개의 거점을 점령한 상태로 시작합니다.
플레이어는 서로 다른 속성을 갖는 유닛을 가지고 게임을 진행하게 됩니다.
== 주요 규칙 ==
보드판 위에는 같은 종류의 유닛 코인(더미)이 동시에 두 군데 이상 놓일 수 없습니다.
보드판 위에 있는 것과 같은 종류의 코인을 앞면으로 사용하면서 보드판 위의 코인을 행동할 수 있습니다.
각 플레이어들은 국왕 코인을 하나씩 갖는데 대개 뒷면으로만 사용 가능하며, 특수한 유닛 전술에 의해 사용되거나 노빌리티 확장에서 칙령을 선포하는 데에 사용되기도 합니다.
플레이어들은 코인을 하나씩 사용하면서 번갈아 가며 차례를 진행하고, 꺼내놓은 코인이 하나도 남지 않았을 때 주머니에서 새로 3개의 코인을 보지 않고 꺼냅니다.
== 턴 진행 ==
자신의 차례에는 꺼내놓은 코인 하나를 선택하여 보드판에 배치하거나 앞면 또는 뒷면으로 버립니다.
=== 배치 ===
코인을 보드판에 배치하기로 선택했다면 자신이 점령하고 있는 비어 있는 거점에 투입하거나, 이미 같은 유닛이 있는 칸에 올려 증원합니다.(증원은 적으로 하여금 해당 유닛을 제거하기 더 어렵게 만듭니다.)
=== 뒷면 버리기 ===
다음 3가지 행동 중 선택합니다.
* 현재 선공 토큰을 가지고 있지 않다면, 다음 라운드의 선공을 선언할 수 있습니다.
* 현재 차례를 건너 뜁니다.(코인 하나는 버리지만, 해당 라운드의 남은 차례는 다시 돌아오게 됩니다.)
* 공급처로부터 코인 하나를 모집하여 버린 영역에 놓습니다. 어떤 유닛을 모집했는지 상대방이 알 수 있도록 앞면으로 공개해 두어야 합니다.
=== 앞면 버리기 ===
버리는 코인과 동일한 유닛을 골라 다음 4가지 작전 중 하나를 선택합니다.
* 인접한 빈 칸으로 코인(더미)을 이동합니다.
* 거점을 점령합니다. 해당 유닛이 현재 위치한 칸에 자신의 점령 마커를 올립니다. 상대의 마커이 있는 경우 거점 밖으로 되돌려 놓고 자신의 마커를 올려두면 됩니다.
* 인접한 적 유닛을 공격합니다. 공격받은 적 유닛은 코인을 게임에서 완전히 제거합니다. 코인이 2개 이상 더미로 쌓여있는 경우에는 하나가 제거되더라도 나머지 코인은 해당 칸에 남아있게 됩니다.
* 유닛의 전술을 활성화합니다. 전술은 각 유닛의 고유 능력으로 유닛 카드에 적혀있습니다. ! 표시는 기본 규칙에 추가되는 능력을 뜻하며, X 표시는 기본 규칙에 제약이 있음을 의미합니다.
=== 기본 규칙 끝 ===
상급 규칙이나 4인 플레이 규칙이 필요하면 아래를 더 보시면 됩니다.
== 상급 규칙 ==
== 4인 플레이(팀 대결) ==
* 각 팀은 시작 시 3개의 거점을 점령한 상태로 시작합니다.
* 각 플레이어들은 3가지 유닛으로 게임을 진행합니다.
* 선공 마커를 가지고 있는 플레이어와 같은 팀인 플레이어는 선공을 가져오는 행동을 할 수 없습니다.
* 두 팀간 플레이어들이 교차로 순서를 진행합니다.
* 점령 마커는 팀원 간에 공유됩니다.(같은 팀원이 점령한 칸은 해당 팀의 점령 칸으로 취급합니다.)
* 모집 행동은 자신의 유닛만 모집할 수 있으며, 팀의 유닛을 대신 모집할 수는 없습니다.
* 같은 팀의 플레이어끼리는 아군 관계입니다. 같은 팀원에 피해를 입힐 수 없습니다.
* 전술로 아군의 유닛이 행동할 수 있는 경우, 같은 팀의 플레이어의 유닛을 행동하게 하는 것도 가능합니다.
* 비밀 토론은 불가하며, 전략적인 상의를 포함한 어떠한 대화도 다른 팀 앞에서 공개적으로 해야 합니다.
a8b68c35384256e975b1c48112ff06f7d59a0b13
1619
1618
2024-06-26T14:16:34Z
Joonseok Kim
9884
wikitext
text/x-wiki
== 개요 ==
이 게임의 목적은 보드판 위의 거점(초록색 칸) 중 6개를 점령한 상태에 먼저 도달하는 것입니다.
게임을 시작할 때 각 플레이어는 두 개의 거점을 점령한 상태로 시작합니다.
플레이어는 서로 다른 속성을 갖는 유닛을 가지고 게임을 진행하게 됩니다.
== 주요 규칙 ==
보드판 위에는 같은 종류의 유닛 코인(더미)이 동시에 두 군데 이상 놓일 수 없습니다.
보드판 위에 있는 것과 같은 종류의 코인을 앞면으로 사용하면서 보드판 위의 코인을 행동할 수 있습니다.
각 플레이어들은 국왕 코인을 하나씩 갖는데 대개 뒷면으로만 사용 가능하며, 특수한 유닛 전술에 의해 사용되거나 노빌리티 확장에서 칙령을 선포하는 데에 사용되기도 합니다.
플레이어들은 코인을 하나씩 사용하면서 번갈아 가며 차례를 진행하고, 모두가 꺼내놓은 코인이 하나도 남지 않았을 때 다음 라운드로 넘어가면서 다시 주머니에서 새로 3개의 코인을 보지 않고 꺼냅니다.
== 턴 진행 ==
자신의 차례에는 꺼내놓은 코인 하나를 선택하여 보드판에 배치하거나 앞면 또는 뒷면으로 버립니다.
=== 배치 ===
코인을 보드판에 배치하기로 선택했다면 자신이 점령하고 있는 비어 있는 거점에 투입하거나, 이미 같은 유닛이 있는 칸에 올려 증원합니다.(증원은 적으로 하여금 해당 유닛을 제거하기 더 어렵게 만듭니다.)
=== 뒷면 버리기 ===
다음 3가지 행동 중 선택합니다.
* 현재 선공 토큰을 가지고 있지 않다면, 다음 라운드의 선공을 선언할 수 있습니다.
* 현재 차례를 건너 뜁니다.(코인 하나는 버리지만, 해당 라운드의 남은 차례는 다시 돌아오게 됩니다.)
* 공급처로부터 코인 하나를 모집하여 버린 영역에 놓습니다. 어떤 유닛을 모집했는지 상대방이 알 수 있도록 앞면으로 공개해 두어야 합니다.
=== 앞면 버리기 ===
버리는 코인과 동일한 유닛을 골라 다음 4가지 작전 중 하나를 선택합니다.
* 인접한 빈 칸으로 코인(더미)을 이동합니다.
* 거점을 점령합니다. 해당 유닛이 현재 위치한 칸에 자신의 점령 마커를 올립니다. 상대의 마커이 있는 경우 거점 밖으로 되돌려 놓고 자신의 마커를 올려두면 됩니다.
* 인접한 적 유닛을 공격합니다. 공격받은 적 유닛은 코인을 게임에서 완전히 제거합니다. 코인이 2개 이상 더미로 쌓여있는 경우에는 하나가 제거되더라도 나머지 코인은 해당 칸에 남아있게 됩니다.
* 유닛의 전술을 활성화합니다. 전술은 각 유닛의 고유 능력으로 유닛 카드에 적혀있습니다. ! 표시는 기본 규칙에 추가되는 능력을 뜻하며, X 표시는 기본 규칙에 제약이 있음을 의미합니다.
=== 기본 규칙 끝 ===
상급 규칙이나 4인 플레이 규칙이 필요하면 아래를 더 보시면 됩니다.
== 상급 규칙 ==
== 4인 플레이(팀 대결) ==
* 각 팀은 시작 시 3개의 거점을 점령한 상태로 시작합니다.
* 각 플레이어들은 3가지 유닛으로 게임을 진행합니다.
* 선공 마커를 가지고 있는 플레이어와 같은 팀인 플레이어는 선공을 가져오는 행동을 할 수 없습니다.
* 두 팀간 플레이어들이 교차로 순서를 진행합니다.
* 점령 마커는 팀원 간에 공유됩니다.(같은 팀원이 점령한 칸은 해당 팀의 점령 칸으로 취급합니다.)
* 모집 행동은 자신의 유닛만 모집할 수 있으며, 팀의 유닛을 대신 모집할 수는 없습니다.
* 같은 팀의 플레이어끼리는 아군 관계입니다. 같은 팀원에 피해를 입힐 수 없습니다.
* 전술로 아군의 유닛이 행동할 수 있는 경우, 같은 팀의 플레이어의 유닛을 행동하게 하는 것도 가능합니다.
* 비밀 토론은 불가하며, 전략적인 상의를 포함한 어떠한 대화도 다른 팀 앞에서 공개적으로 해야 합니다.
1b8c11c373ff9bde6c89b66ac67a4112704ff04c
Gamehelpgizmos
0
245
1620
1473
2024-06-28T13:49:44Z
Moonyo
7890
wikitext
text/x-wiki
== 개요 ==
기즈모는 엔진 빌딩 자원 관리 게임입니다. 여러분은 하나의 액션으로 구성된 간단한 턴부터 시작하여 엔진을 빌드업하여 한 턴에 많은 액션을 발동할 수 있는 지점까지 진행할 것입니다
플레이어의 차례입니다
다음 작업 중 하나를 수행해야 합니다:
수집: 디스플레이 영역에서 기즈모를 하나 수집합니다.
획득: 에너지 레일에서 선택한 에너지 1개를 획득합니다.
제작: 디스플레이 영역 또는 아카이브에서 1개의 기즈모를 빌드합니다.
연구: 3개의 레벨 덱 중 하나에서 기즈모 카드를 뽑고 수집 또는 제작할 1개를 선택합니다
==수집==
디스플레이 영역에서 1개의 기즈모 카드를 선택한 다음 수집을 선택합니다. 기즈모 수집 후 즉시 해당 덱의 상단 카드로 교체됩니다. 이 새 기즈모를 뽑으면 수집 작업이 종료됩니다.
플레이어 대시보드의 업그레이드 영역에 표시된 만큼 수집에는 수집할 수 있는 기즈모 수가 제한됩니다. 각 플레이어는 수집 제한을 1로 설정하고 게임을 시작하지만, 일부 업그레이드 기즈모는 이 수를 늘립니다. 보관 파일은 파일 제한보다 많은 크기를 보관할 수 없으므로, 제한에 도달하면 파일 작업을 수행할 수 없습니다.
==획득==
에너지 레일에 있는 6개 중 1개의 에너지를 선택하여 에너지 저장 링에 추가합니다. 플레이어 대시보드의 업그레이드 영역에 표시된 만큼 에너지 저장 링에 저장할 수 있는 에너지가 제한되어 있습니다. 각 플레이어는 저장 제한을 5로 설정하고 게임을 시작하지만 일부 압그레이드 기즈모는 이 수를 늘릴 것입니다. 링에는 에너지 저장 한도 이상의 에너지를 저장할 수 없으므로, 한계에 도달하면 기존의 에너지를 사용하지 않는 한 더 이상의 에너지를 수집할 수 없습니다.
중요: 일부 기능을 사용하면 임의 에너지를 뽑을 수 있습니다. 이 작업은 획득 작업이 아니므로 다른 작업을 트리거하지 않습니다.
==제작==
디스플레이 영역 또는 아카이브에서 1개의 기즈모 카드를 선택합니다. 기즈모의 에너지 유형과 비용에 맞는 에너지 저장 링의 에너지를 사용하십시오. 디스플레이 영역에서 기즈모를 만든 후 즉시 해당 덱 상단에서 새로운 기즈모로 교체됩니다. 보충 후 제작 작업이 종료됩니다.
제작한 기즈모는 플레이어 대시보드 아래로 이동하여 모든 효과를 볼 수 있습니다.
==변환==
제작 작업을 수행할 때 변환 기즈모를 사용하여 보유한 에너지를 필요한 에너지로 변환할 수 있습니다. 보유한 변환기를 선택하여 이 작업을 수행할 수 있습니다. 변환기 유형에 대한 자세한 내용은 링크된 효과 목록 PDF에서 확인할 수 있습니다.
==연구==
레벨 덱(1, 2 또는 3)을 선택하고 연구량과 동일한 카드 수를 그립니다. 한 번에 두 개 이상의 레벨 덱에서 뽑을 수 없습니다. 각 플레이어는 연구량 3으로 게임을 시작하지만, 일부 업그레이드 기즈모는 그 수를 늘립니다. 선택한 레벨 덱의 카드 수가 연구량 보다 적을 경우 사용 가능한 카드 수만 뽑습니다. 카드를 뽑은 후 1개를 선택하고 제작(에너지가 충분한 경우) 또는 수집(Archive에 공간이 있는 경우)을 선택합니다. 또는 둘 다 수행하지 않고 통과하도록 선택할 수 있습니다.
그런 다음 나머지 카드는 선택한 순서대로 해당 레벨 덱의 맨 아래로 돌아갑니다.
참고: 연구 작업 중에 수행하는 파일 또는 빌드 작업도 기즈모를 트리거하는 데 카운트됩니다(아래 Gizmo 효과 트리거 참조).
==기즈모 효과 트리거==
사용 가능한 4가지 액션 중 하나를 취하는 것이 게임의 기본이지만, 게임의 진정한 핵심(그리고 승리의 열쇠)은 당신의 차례에 훨씬 더 많은 것을 얻기 위해 당신의 기즈모의 효과를 발동시키는 것입니다. 플레이어 대시보드 아래에 제작하고 배치하는 모든 기즈모에는 특정 트리거에 의해 활성화되는 효과가 있습니다(이에 대한 자세한 내용은 효과 목록의 링크된 PDF 참조). 작업을 수행할 때마다 트리거된 기즈모가 강조 표시됩니다. 트리거 작업이 완료된 후 원하는 순서로 트리거된 기즈모의 효과를 활성화할 수 있습니다. 트리거 조건이 두 번 이상 충족되더라도 각 기즈모는 한 번에 한 번만 사용할 수 있습니다.
참고: 기즈모가 만들어진 턴에도 기즈모의 효과를 사용할 수 있습니다. 그러나 제작한 작업과 동일한 작업에 의해 트리거될 수 없습니다.
==연쇄 반응==
최고의 발명가들의 비밀은 하나의 기즈모가 다른 기즈모를 촉발시켜 많은 이익을 창출하는 연쇄 반응을 일으킬 방법으로 기즈모를 민드는 것입니다! 기즈모 하나의 효과는 원래 수행된 액션과 다른 액션일 수 있습니다. 그런 다음 보조 작업을 수행하면 다른 기즈모를 트리거할 수 있습니다. 작업을 수행할 때마다 해당 순서에 대한 하나의 작업이든, 기즈모 효과에 의해 트리거된 작업이든 상관없이 항상 해당 작업의 기즈모를 확인하여 트리거된 작업이 있는지 확인하십시오.
활성화할 수 있는 기즈모의 수에는 제한이 없지만, 각 기즈모는 한 번에 한 번만 사용할 수 있다는 것을 항상 기억하십시오.
각 Gizmo의 효과가 실행되는 순서는 효과가 발생한 순서에 관계없이 플레이어에게 달려 있습니다. 연쇄 반응의 처음에 만들어진 기즈모는 그것을 만든 행동에 의해 촉발되지 않는 한, 그 연쇄 반응의 나중에 활성화될 수 있습니다. 때로는 작업과 효과를 실행하기 위한 최적의 순서를 찾는 것이 더 큰 결과를 얻을 수 있습니다.
==게임의 끝==
게임의 끝은 플레이어가 4번째 레벨 3 기즈모 또는 16번째 기즈모(시작 기즈모 포함)를 제작할 때 입니다. 그러면 첫 번째 플레이어의 오른쪽에 있는 플레이어가 차례를 마칠 때까지 게임이 계속됩니다. 즉, 모든 플레이어가 게임에서 동일한 턴 수를 가질 때까지입니다. 게임 종료를 트리거한 플레이어가 첫 번째 플레이어의 오른쪽에 있는 플레이어일 경우, 차례가 끝나면 게임이 종료됩니다.
당연히 승리 포인트가 가장 많은 선수가 승리합니다! 동점일 경우, 액티브 기즈모 영역에서 가장 많은 기즈모를 가진 동점자가 승리합니다(필드 기즈모는 포함되지 않음). 여전히 동점일 경우, 에너지 저장 링에 가장 많은 에너지가 남아 있는 동점자가 승리합니다. 그래도 동점일 경우 레벨 3 기즈모가 많은 사람이 승리하고, 그래도 동점일 경우 첫 번째 플레이어에서 가장 멀리 있는 동점자가 승리합니다.
9c57f4dca4f29b1a5525036c0483de4ef8e0a4e2
Gamehelpcartographers
0
295
1621
2024-07-02T12:12:20Z
Moonyo
7890
새 문서: ===개요=== 지도 제작자(Cartographers)는 각 플레이어가 자신의 땅에 대한 지도를 별도로 그리는 플립 앤 쓰기 게임입니다. 각 라운드마다 지도에 지형지물을 추가하고, 몇 라운드 후에는 이러한 지형지물의 존재 여부나 배열에 따라 점수를 매깁니다. 4라운드가 끝난 후 가장 많은 점수를 얻은 플레이어가 게임에서 승리합니다! ===게임 구성 요소=== 각 플레이어는 지도...
wikitext
text/x-wiki
===개요===
지도 제작자(Cartographers)는 각 플레이어가 자신의 땅에 대한 지도를 별도로 그리는 플립 앤 쓰기 게임입니다. 각 라운드마다 지도에 지형지물을 추가하고, 몇 라운드 후에는 이러한 지형지물의 존재 여부나 배열에 따라 점수를 매깁니다. 4라운드가 끝난 후 가장 많은 점수를 얻은 플레이어가 게임에서 승리합니다!
===게임 구성 요소===
각 플레이어는 지도를 가지고 있습니다. 이 지도는 대부분 공백으로 시작하지만 산, 폐허, 황무지 공간이 이미 포함되어 있을 수 있습니다.
테이블 전체에는 A부터 D까지 라벨이 붙은 4개의 점수 카드가 포함되어 있습니다. 이 카드는 특정 형식을 취합니다.
이 카드 중 하나는 마을 공간을 찾습니다.
이 카드 중 하나는 숲 공간을 찾습니다.
이 카드 중 하나는 물과 농장 공간을 찾습니다.
이 카드 중 하나는 전체 지도를 살펴보며 일반적으로 지도의 특정 부분을 무엇이든 채우는 데 중점을 둡니다.
또한 시즌 카드도 포함되어 있으며, 라운드가 끝날 때 이 카드 중 두 개가 득점될 것이며 라운드에서 뒤집힐 카드 수를 알려줍니다.
봄은 8시간 단위로 지속되며 플레이어는 카드 A와 B를 득점합니다.
여름은 8시간 단위로 지속되며 플레이어는 카드 B와 C에 점수를 매깁니다.
가을은 7시간 단위로 지속되며 플레이어는 카드 C와 D를 득점합니다.
겨울은 6시간 단위로 지속되며, 플레이어는 D와 A 카드에 점수를 매깁니다.
또한 테이블에는 다양한 풍경을 그리는 데 사용되는 카드 덱이 포함되어 있습니다.
===당신 차례에 무엇을 해야 할까요?===
풍경 덱의 맨 위 카드를 뒤집어 모든 플레이어가 동시에 지도의 어딘가에 카드를 그립니다. 이 카드에는 일반적으로 동일한 모양으로 두 가지 다른 지형 유형을 수행하거나 두 모양 중 하나에서 하나의 특정 지형을 수행할 수 있는 선택 사항이 포함되어 있습니다. 이러한 모양은 90도 단위로 뒤집거나 회전할 수 있으며 지도의 어느 곳에나 배치할 수 있습니다. 어떤 항목에도 인접할 필요가 없습니다. 이러한 모양은 지도 가장자리에 걸 수 없으며 채워진 공간과 겹칠 수도 없습니다.
플레이어가 특정 모양을 그릴 수 없는 경우 대신 보드의 아무 곳에나 지형 유형의 단일 1x1 정사각형을 그립니다.
일부 작은 모양에는 금화가 들어 있습니다. 그 모양을 그리면 지도 옆에 있는 동전에 줄을 그으세요. 이는 각 득점 단계마다 1점의 가치가 있습니다. 보드의 산 공간에 인접한 4개의 공간을 모두 채워 코인을 얻을 수도 있습니다.
각 카드의 왼쪽 상단에는 경과된 시간을 나타내는 숫자가 있습니다. 이런 식으로 플레이한 모든 카드의 합이 시즌 카드의 숫자보다 크거나 같으면 모든 플레이어가 이 모양을 그린 후에 라운드가 종료됩니다. 그렇지 않으면 다음 턴을 시작합니다.
===특수 카드===
덱에는 유적 카드가 2장 있습니다. 폐허 카드를 뽑은 경우 다음 모양은 보드의 폐허 공간 중 하나와 겹쳐야 합니다. 이 모양을 그리는 데 대한 다른 모든 규칙은 여전히 적용됩니다.
매 시즌마다 덱에 하나의 몬스터 카드가 추가됩니다. 괴물 카드가 뽑히면 모든 플레이어는 자신의 지도를 다른 플레이어에게 전달합니다. 그런 다음 상대방 보드에 이 괴물 모양을 그립니다. 이 괴물을 그리는 데 관한 다른 모든 규칙은 여전히 적용됩니다. 플레이어는 몬스터 옆의 빈 공간마다 점수를 잃습니다. 그 후, 이 괴물 카드는 게임에서 제거됩니다(그러나 발견되지 않으면 다음 시즌 동안 덱에 남아 있습니다).
덱에는 Rift Lands 카드가 1장 있습니다. 리프트 랜드(Rift Lands) 카드를 뽑으면 모든 플레이어는 자신의 보드 어디에든 지형 유형에 관계없이 1x1 정사각형을 그립니다.
===라운드 종료===
각 라운드가 끝나면 4개의 점수 카드 중 2개가 결정됩니다.
봄은 8시간 단위로 지속되며 플레이어는 카드 A와 B를 득점합니다.
여름은 8시간 단위로 지속되며 플레이어는 카드 B와 C에 점수를 매깁니다.
가을은 7시간 단위로 지속되며 플레이어는 카드 C와 D를 득점합니다.
겨울은 6시간 단위로 지속되며 플레이어는 카드 D와 A를 기록합니다.
또한 매 라운드마다 플레이어는 자신이 보유한 금화당 1점을 얻고, 몬스터 옆의 빈 공간마다 1점을 잃습니다.
점수를 매긴 후 조경 데크를 다시 섞습니다.
Winter의 점수가 나오면 게임이 종료되고 가장 많은 점수를 얻은 플레이어가 승리합니다!
-----------------------------------------
OVERVIEW
Cartographers is a flip-and-write game in which each of the players are separately drawing a map of their land. Each round, you'll add a feature to your map, and after a few rounds, you'll score based on the presence or arrangement of these features. The player with the most points at the end of four rounds wins the game!
GAME COMPONENTS
Each player has a map. This map starts mostly blank, but may have mountains, ruins, and wasteland spaces already included.
The table as a whole contains four scoring cards, labeled A through D. These take a specific format:
One of these cards looks for village spaces
One of these cards looks for forest spaces
One of these cards looks for water and farm spaces
One of these cards looks at the whole map, usually around filling certain segments of it with anything at all.
It also contains season cards, which say which two of these cards will be scored at the end of the round and how many cards will be flipped in the round:
Spring lasts 8 time units, and players score cards A and B.
Summer lasts 8 time units, and players score cards B and C.
Autumn lasts 7 time units, and players score cards C and D.
Winter lasts 6 time units, and players score cards D and A.
In addition, the table contains the deck of cards used to draw various landscapes.
WHAT TO DO ON YOUR TURN
The top card of the landscape deck is flipped, and all players simultaneously draw that somewhere on the map. These cards usually contain a choice to do two different terrain types in the same shape, or one specific terrain in one of two shapes. These shapes can be flipped or rotated in any 90 degree increment, and can be placed anywhere on the map - it does not need to be adjacent to anything. These shapes can't hang off the edge of the map, nor can they overlap any filled space.
If any player can't draw a particular shape, they instead draw a single 1x1 square of any terrain type anywhere on their board.
Some smaller shapes contain a gold coin. If you draw that shape, cross off a coin on the side of your map. This will be worth 1 point each scoring phase. You can also earn coins by filling all four spaces adjacent to a mountain space on your board.
Each of these cards has a number on the top left corner indicating how much time has passed. If the sum of all cards played this way is greater than or equal to the number on the season card, the round ends after all players have drawn this shape. Otherwise, start the next turn.
SPECIAL CARDS
There are two Ruins cards in the deck. If the Ruins card is drawn, the next shape must overlap with one of the ruins spaces on your board. All other rules about drawing this shape still apply.
There is one Monster card added to the deck each season. If a Monster card is drawn, all players pass their maps to another player. Then draw this monster shape on your opponent's board. All other rules about drawing this monster still apply. Players will lose points for each empty space next to monsters. Afterwards, this Monster card is removed from play (but if it's never found, it remains in the deck for the next season).
There is one Rift Lands card in the deck. If a Rift Lands card is drawn, all players draw a 1x1 square of any terrain type anywhere on their board.
END OF A ROUND
At the end of each round, two of the four scoring cards will be resolved.
Spring lasts 8 time units, and players score cards A and B.
Summer lasts 8 time units, and players score cards B and C.
Autumn lasts 7 time units, and players score cards C and D.
Winter lasts 6 time units, and players score cards D and A.
In addition to this, every round players score 1 point for each gold coin they have, and lose 1 point for each empty space next to monsters.
After scoring, the landscape deck is reshuffled.
Once Winter is scored, the game ends, and the player with the most points wins!
7ce4345cbf22d69021531791f4c612cba8bd30e0
1622
1621
2024-07-02T12:12:47Z
Moonyo
7890
wikitext
text/x-wiki
===개요===
지도 제작자(Cartographers)는 각 플레이어가 자신의 땅에 대한 지도를 별도로 그리는 플립 앤 쓰기 게임입니다. 각 라운드마다 지도에 지형지물을 추가하고, 몇 라운드 후에는 이러한 지형지물의 존재 여부나 배열에 따라 점수를 매깁니다. 4라운드가 끝난 후 가장 많은 점수를 얻은 플레이어가 게임에서 승리합니다!
===게임 구성 요소===
각 플레이어는 지도를 가지고 있습니다. 이 지도는 대부분 공백으로 시작하지만 산, 폐허, 황무지 공간이 이미 포함되어 있을 수 있습니다.
테이블 전체에는 A부터 D까지 라벨이 붙은 4개의 점수 카드가 포함되어 있습니다. 이 카드는 특정 형식을 취합니다.
이 카드 중 하나는 마을 공간을 찾습니다.
이 카드 중 하나는 숲 공간을 찾습니다.
이 카드 중 하나는 물과 농장 공간을 찾습니다.
이 카드 중 하나는 전체 지도를 살펴보며 일반적으로 지도의 특정 부분을 무엇이든 채우는 데 중점을 둡니다.
또한 시즌 카드도 포함되어 있으며, 라운드가 끝날 때 이 카드 중 두 개가 득점될 것이며 라운드에서 뒤집힐 카드 수를 알려줍니다.
봄은 8시간 단위로 지속되며 플레이어는 카드 A와 B를 득점합니다.
여름은 8시간 단위로 지속되며 플레이어는 카드 B와 C에 점수를 매깁니다.
가을은 7시간 단위로 지속되며 플레이어는 카드 C와 D를 득점합니다.
겨울은 6시간 단위로 지속되며, 플레이어는 D와 A 카드에 점수를 매깁니다.
또한 테이블에는 다양한 풍경을 그리는 데 사용되는 카드 덱이 포함되어 있습니다.
===당신 차례에 무엇을 해야 할까요?===
풍경 덱의 맨 위 카드를 뒤집어 모든 플레이어가 동시에 지도의 어딘가에 카드를 그립니다. 이 카드에는 일반적으로 동일한 모양으로 두 가지 다른 지형 유형을 수행하거나 두 모양 중 하나에서 하나의 특정 지형을 수행할 수 있는 선택 사항이 포함되어 있습니다. 이러한 모양은 90도 단위로 뒤집거나 회전할 수 있으며 지도의 어느 곳에나 배치할 수 있습니다. 어떤 항목에도 인접할 필요가 없습니다. 이러한 모양은 지도 가장자리에 걸 수 없으며 채워진 공간과 겹칠 수도 없습니다.
플레이어가 특정 모양을 그릴 수 없는 경우 대신 보드의 아무 곳에나 지형 유형의 단일 1x1 정사각형을 그립니다.
일부 작은 모양에는 금화가 들어 있습니다. 그 모양을 그리면 지도 옆에 있는 동전에 줄을 그으세요. 이는 각 득점 단계마다 1점의 가치가 있습니다. 보드의 산 공간에 인접한 4개의 공간을 모두 채워 코인을 얻을 수도 있습니다.
각 카드의 왼쪽 상단에는 경과된 시간을 나타내는 숫자가 있습니다. 이런 식으로 플레이한 모든 카드의 합이 시즌 카드의 숫자보다 크거나 같으면 모든 플레이어가 이 모양을 그린 후에 라운드가 종료됩니다. 그렇지 않으면 다음 턴을 시작합니다.
===특수 카드===
덱에는 유적 카드가 2장 있습니다. 폐허 카드를 뽑은 경우 다음 모양은 보드의 폐허 공간 중 하나와 겹쳐야 합니다. 이 모양을 그리는 데 대한 다른 모든 규칙은 여전히 적용됩니다.
매 시즌마다 덱에 하나의 몬스터 카드가 추가됩니다. 괴물 카드가 뽑히면 모든 플레이어는 자신의 지도를 다른 플레이어에게 전달합니다. 그런 다음 상대방 보드에 이 괴물 모양을 그립니다. 이 괴물을 그리는 데 관한 다른 모든 규칙은 여전히 적용됩니다. 플레이어는 몬스터 옆의 빈 공간마다 점수를 잃습니다. 그 후, 이 괴물 카드는 게임에서 제거됩니다(그러나 발견되지 않으면 다음 시즌 동안 덱에 남아 있습니다).
덱에는 Rift Lands 카드가 1장 있습니다. 리프트 랜드(Rift Lands) 카드를 뽑으면 모든 플레이어는 자신의 보드 어디에든 지형 유형에 관계없이 1x1 정사각형을 그립니다.
===라운드 종료===
각 라운드가 끝나면 4개의 점수 카드 중 2개가 결정됩니다.
봄은 8시간 단위로 지속되며 플레이어는 카드 A와 B를 득점합니다.
여름은 8시간 단위로 지속되며 플레이어는 카드 B와 C에 점수를 매깁니다.
가을은 7시간 단위로 지속되며 플레이어는 카드 C와 D를 득점합니다.
겨울은 6시간 단위로 지속되며 플레이어는 카드 D와 A를 기록합니다.
또한 매 라운드마다 플레이어는 자신이 보유한 금화당 1점을 얻고, 몬스터 옆의 빈 공간마다 1점을 잃습니다.
점수를 매긴 후 조경 데크를 다시 섞습니다.
Winter의 점수가 나오면 게임이 종료되고 가장 많은 점수를 얻은 플레이어가 승리합니다!
-----------------------------------------
OVERVIEW
Cartographers is a flip-and-write game in which each of the players are separately drawing a map of their land. Each round, you'll add a feature to your map, and after a few rounds, you'll score based on the presence or arrangement of these features. The player with the most points at the end of four rounds wins the game!
GAME COMPONENTS
Each player has a map. This map starts mostly blank, but may have mountains, ruins, and wasteland spaces already included.
The table as a whole contains four scoring cards, labeled A through D. These take a specific format:
One of these cards looks for village spaces
One of these cards looks for forest spaces
One of these cards looks for water and farm spaces
One of these cards looks at the whole map, usually around filling certain segments of it with anything at all.
It also contains season cards, which say which two of these cards will be scored at the end of the round and how many cards will be flipped in the round:
Spring lasts 8 time units, and players score cards A and B.
Summer lasts 8 time units, and players score cards B and C.
Autumn lasts 7 time units, and players score cards C and D.
Winter lasts 6 time units, and players score cards D and A.
In addition, the table contains the deck of cards used to draw various landscapes.
WHAT TO DO ON YOUR TURN
The top card of the landscape deck is flipped, and all players simultaneously draw that somewhere on the map. These cards usually contain a choice to do two different terrain types in the same shape, or one specific terrain in one of two shapes. These shapes can be flipped or rotated in any 90 degree increment, and can be placed anywhere on the map - it does not need to be adjacent to anything. These shapes can't hang off the edge of the map, nor can they overlap any filled space.
If any player can't draw a particular shape, they instead draw a single 1x1 square of any terrain type anywhere on their board.
Some smaller shapes contain a gold coin. If you draw that shape, cross off a coin on the side of your map. This will be worth 1 point each scoring phase. You can also earn coins by filling all four spaces adjacent to a mountain space on your board.
Each of these cards has a number on the top left corner indicating how much time has passed. If the sum of all cards played this way is greater than or equal to the number on the season card, the round ends after all players have drawn this shape. Otherwise, start the next turn.
SPECIAL CARDS
There are two Ruins cards in the deck. If the Ruins card is drawn, the next shape must overlap with one of the ruins spaces on your board. All other rules about drawing this shape still apply.
There is one Monster card added to the deck each season. If a Monster card is drawn, all players pass their maps to another player. Then draw this monster shape on your opponent's board. All other rules about drawing this monster still apply. Players will lose points for each empty space next to monsters. Afterwards, this Monster card is removed from play (but if it's never found, it remains in the deck for the next season).
There is one Rift Lands card in the deck. If a Rift Lands card is drawn, all players draw a 1x1 square of any terrain type anywhere on their board.
END OF A ROUND
At the end of each round, two of the four scoring cards will be resolved.
Spring lasts 8 time units, and players score cards A and B.
Summer lasts 8 time units, and players score cards B and C.
Autumn lasts 7 time units, and players score cards C and D.
Winter lasts 6 time units, and players score cards D and A.
In addition to this, every round players score 1 point for each gold coin they have, and lose 1 point for each empty space next to monsters.
After scoring, the landscape deck is reshuffled.
Once Winter is scored, the game ends, and the player with the most points wins!
9010a035a491ac4f852b0cccedd1bee935435e8a
1623
1622
2024-07-02T12:30:31Z
Moonyo
7890
wikitext
text/x-wiki
===개요===
지도 제작자(Cartographers)는 각 플레이어가 자신의 땅에 대한 지도를 별도로 그리는 플립 앤 쓰기 게임입니다. 각 라운드마다 지도에 지형지물을 추가하고, 몇 라운드 후에는 이러한 지형지물의 존재 여부나 배열에 따라 점수를 매깁니다. 4라운드가 끝난 후 가장 많은 점수를 얻은 플레이어가 게임에서 승리합니다!
===게임 구성 요소===
각 플레이어는 지도를 가지고 있습니다. 이 지도는 대부분 공백으로 시작하지만 산, 폐허, 황무지 공간이 이미 포함되어 있을 수 있습니다.
테이블 전체에는 A부터 D까지 라벨이 붙은 4개의 점수 카드가 포함되어 있습니다. 이 카드는 특정 형식을 취합니다.
이 카드 중 하나는 마을 공간을 찾습니다.
이 카드 중 하나는 숲 공간을 찾습니다.
이 카드 중 하나는 물과 농장 공간을 찾습니다.
이 카드 중 하나는 전체 지도를 살펴보며 일반적으로 지도의 특정 부분을 무엇이든 채우는 데 중점을 둡니다.
또한 시즌 카드도 포함되어 있으며, 라운드가 끝날 때 이 카드 중 두 개가 득점될 것이며 라운드에서 뒤집힐 카드 수를 알려줍니다.
봄은 8시간 단위로 지속되며 플레이어는 카드 A와 B를 득점합니다.
여름은 8시간 단위로 지속되며 플레이어는 카드 B와 C에 점수를 매깁니다.
가을은 7시간 단위로 지속되며 플레이어는 카드 C와 D를 득점합니다.
겨울은 6시간 단위로 지속되며, 플레이어는 D와 A 카드에 점수를 매깁니다.
또한 테이블에는 다양한 풍경을 그리는 데 사용되는 카드 덱이 포함되어 있습니다.
===당신 차례에 무엇을 해야 할까요?===
풍경 덱의 맨 위 카드를 뒤집어 모든 플레이어가 동시에 지도의 어딘가에 카드를 그립니다. 이 카드에는 일반적으로 동일한 모양으로 두 가지 다른 지형 유형을 수행하거나 두 모양 중 하나에서 하나의 특정 지형을 수행할 수 있는 선택 사항이 포함되어 있습니다. 이러한 모양은 90도 단위로 뒤집거나 회전할 수 있으며 지도의 어느 곳에나 배치할 수 있습니다. 어떤 항목에도 인접할 필요가 없습니다. 이러한 모양은 지도 가장자리에 걸 수 없으며 채워진 공간과 겹칠 수도 없습니다.
플레이어가 특정 모양을 그릴 수 없는 경우 대신 보드의 아무 곳에나 지형 유형의 단일 1x1 정사각형을 그립니다.
일부 작은 모양에는 금화가 들어 있습니다. 그 모양을 그리면 지도 옆에 있는 동전에 줄을 그으세요. 이는 각 득점 단계마다 1점의 가치가 있습니다. 보드의 산 공간에 인접한 4개의 공간을 모두 채워 코인을 얻을 수도 있습니다.
각 카드의 왼쪽 상단에는 경과된 시간을 나타내는 숫자가 있습니다. 이런 식으로 플레이한 모든 카드의 합이 시즌 카드의 숫자보다 크거나 같으면 모든 플레이어가 이 모양을 그린 후에 라운드가 종료됩니다. 그렇지 않으면 다음 턴을 시작합니다.
===특수 카드===
덱에는 유적 카드가 2장 있습니다. 폐허 카드를 뽑은 경우 다음 모양은 보드의 폐허 공간 중 하나와 겹쳐야 합니다. 이 모양을 그리는 데 대한 다른 모든 규칙은 여전히 적용됩니다.
매 시즌마다 덱에 하나의 몬스터 카드가 추가됩니다. 괴물 카드가 뽑히면 모든 플레이어는 자신의 지도를 다른 플레이어에게 전달합니다. 그런 다음 상대방 보드에 이 괴물 모양을 그립니다. 이 괴물을 그리는 데 관한 다른 모든 규칙은 여전히 적용됩니다. 플레이어는 몬스터 옆의 빈 공간마다 점수를 잃습니다. 그 후, 이 괴물 카드는 게임에서 제거됩니다(그러나 발견되지 않으면 다음 시즌 동안 덱에 남아 있습니다).
덱에는 Rift Lands 카드가 1장 있습니다. 리프트 랜드(Rift Lands) 카드를 뽑으면 모든 플레이어는 자신의 보드 어디에든 지형 유형에 관계없이 1x1 정사각형을 그립니다.
===라운드 종료===
각 라운드가 끝나면 4개의 점수 카드 중 2개가 결정됩니다.
봄은 8시간 단위로 지속되며 플레이어는 카드 A와 B를 득점합니다.
여름은 8시간 단위로 지속되며 플레이어는 카드 B와 C에 점수를 매깁니다.
가을은 7시간 단위로 지속되며 플레이어는 카드 C와 D를 득점합니다.
겨울은 6시간 단위로 지속되며 플레이어는 카드 D와 A를 기록합니다.
또한 매 라운드마다 플레이어는 자신이 보유한 금화당 1점을 얻고, 몬스터 옆의 빈 공간마다 1점을 잃습니다.
점수를 매긴 후 조경 데크를 다시 섞습니다.
Winter의 점수가 나오면 게임이 종료되고 가장 많은 점수를 얻은 플레이어가 승리합니다!
-----------------------------------------
===OVERVIEW===
Cartographers is a flip-and-write game in which each of the players are separately drawing a map of their land. Each round, you'll add a feature to your map, and after a few rounds, you'll score based on the presence or arrangement of these features. The player with the most points at the end of four rounds wins the game!
===GAME COMPONENTS===
Each player has a map. This map starts mostly blank, but may have mountains, ruins, and wasteland spaces already included.
The table as a whole contains four scoring cards, labeled A through D. These take a specific format:
One of these cards looks for village spaces
One of these cards looks for forest spaces
One of these cards looks for water and farm spaces
One of these cards looks at the whole map, usually around filling certain segments of it with anything at all.
It also contains season cards, which say which two of these cards will be scored at the end of the round and how many cards will be flipped in the round:
Spring lasts 8 time units, and players score cards A and B.
Summer lasts 8 time units, and players score cards B and C.
Autumn lasts 7 time units, and players score cards C and D.
Winter lasts 6 time units, and players score cards D and A.
In addition, the table contains the deck of cards used to draw various landscapes.
===WHAT TO DO ON YOUR TURN===
The top card of the landscape deck is flipped, and all players simultaneously draw that somewhere on the map. These cards usually contain a choice to do two different terrain types in the same shape, or one specific terrain in one of two shapes. These shapes can be flipped or rotated in any 90 degree increment, and can be placed anywhere on the map - it does not need to be adjacent to anything. These shapes can't hang off the edge of the map, nor can they overlap any filled space.
If any player can't draw a particular shape, they instead draw a single 1x1 square of any terrain type anywhere on their board.
Some smaller shapes contain a gold coin. If you draw that shape, cross off a coin on the side of your map. This will be worth 1 point each scoring phase. You can also earn coins by filling all four spaces adjacent to a mountain space on your board.
Each of these cards has a number on the top left corner indicating how much time has passed. If the sum of all cards played this way is greater than or equal to the number on the season card, the round ends after all players have drawn this shape. Otherwise, start the next turn.
===SPECIAL CARDS===
There are two Ruins cards in the deck. If the Ruins card is drawn, the next shape must overlap with one of the ruins spaces on your board. All other rules about drawing this shape still apply.
There is one Monster card added to the deck each season. If a Monster card is drawn, all players pass their maps to another player. Then draw this monster shape on your opponent's board. All other rules about drawing this monster still apply. Players will lose points for each empty space next to monsters. Afterwards, this Monster card is removed from play (but if it's never found, it remains in the deck for the next season).
There is one Rift Lands card in the deck. If a Rift Lands card is drawn, all players draw a 1x1 square of any terrain type anywhere on their board.
===END OF A ROUND===
At the end of each round, two of the four scoring cards will be resolved.
Spring lasts 8 time units, and players score cards A and B.
Summer lasts 8 time units, and players score cards B and C.
Autumn lasts 7 time units, and players score cards C and D.
Winter lasts 6 time units, and players score cards D and A.
In addition to this, every round players score 1 point for each gold coin they have, and lose 1 point for each empty space next to monsters.
After scoring, the landscape deck is reshuffled.
Once Winter is scored, the game ends, and the player with the most points wins!
c13b89eb8346a54896b7aa0c1330fda3f65ca139
1624
1623
2024-07-02T12:37:39Z
Moonyo
7890
wikitext
text/x-wiki
===개요===
지도 제작자(Cartographers)는 각 플레이어가 자신의 땅에 대한 지도를 별도로 그리는 플립 앤 쓰기 게임입니다. 각 라운드마다 지도에 지형지물을 추가하고, 몇 라운드 후에는 이러한 지형지물의 존재 여부나 배열에 따라 점수를 매깁니다. 4라운드가 끝난 후 가장 많은 점수를 얻은 플레이어가 게임에서 승리합니다!
===게임 구성 요소===
각 플레이어는 지도를 가지고 있습니다. 이 지도는 대부분 공백으로 시작하지만 산, 폐허, 황무지 공간이 이미 포함되어 있을 수 있습니다.
테이블 전체에는 A부터 D까지 라벨이 붙은 4개의 점수 카드가 포함되어 있습니다. 이 카드는 특정 형식을 취합니다.
이 카드 중 하나는 마을 공간을 찾습니다.
이 카드 중 하나는 숲 공간을 찾습니다.
이 카드 중 하나는 물과 농장 공간을 찾습니다.
이 카드 중 하나는 전체 지도를 살펴보며 일반적으로 지도의 특정 부분을 무엇이든 채우는 데 중점을 둡니다.
또한 시즌 카드도 포함되어 있으며, 라운드가 끝날 때 이 카드 중 두 개가 득점될 것이며 라운드에서 뒤집힐 카드 수를 알려줍니다.
봄은 8시간 단위로 지속되며 플레이어는 카드 A와 B를 득점합니다.
여름은 8시간 단위로 지속되며 플레이어는 카드 B와 C에 점수를 매깁니다.
가을은 7시간 단위로 지속되며 플레이어는 카드 C와 D를 득점합니다.
겨울은 6시간 단위로 지속되며, 플레이어는 D와 A 카드에 점수를 매깁니다.
또한 테이블에는 다양한 풍경을 그리는 데 사용되는 카드 덱이 포함되어 있습니다.
===당신 차례에 무엇을 해야 할까요?===
풍경 덱의 맨 위 카드를 뒤집어 모든 플레이어가 동시에 지도의 어딘가에 카드를 그립니다. 이 카드에는 일반적으로 동일한 모양으로 두 가지 다른 지형 유형을 수행하거나 두 모양 중 하나에서 하나의 특정 지형을 수행할 수 있는 선택 사항이 포함되어 있습니다. 이러한 모양은 90도 단위로 뒤집거나 회전할 수 있으며 지도의 어느 곳에나 배치할 수 있습니다. 어떤 항목에도 인접할 필요가 없습니다. 이러한 모양은 지도 가장자리에 걸 수 없으며 채워진 공간과 겹칠 수도 없습니다.
플레이어가 특정 모양을 그릴 수 없는 경우 대신 보드의 아무 곳에나 지형 유형의 단일 1x1 정사각형을 그립니다.
일부 작은 모양에는 금화가 들어 있습니다. 그 모양을 그리면 지도 옆에 있는 동전에 줄을 그으세요. 이는 각 득점 단계마다 1점의 가치가 있습니다. 보드의 산 공간에 인접한 4개의 공간을 모두 채워 코인을 얻을 수도 있습니다.
각 카드의 왼쪽 상단에는 경과된 시간을 나타내는 숫자가 있습니다. 이런 식으로 플레이한 모든 카드의 합이 시즌 카드의 숫자보다 크거나 같으면 모든 플레이어가 이 모양을 그린 후에 라운드가 종료됩니다. 그렇지 않으면 다음 턴을 시작합니다.
===특수 카드===
덱에는 유적 카드가 2장 있습니다. 폐허 카드를 뽑은 경우 다음 모양은 보드의 폐허 공간 중 하나와 겹쳐야 합니다. 이 모양을 그리는 데 대한 다른 모든 규칙은 여전히 적용됩니다.
매 시즌마다 덱에 하나의 몬스터 카드가 추가됩니다. 괴물 카드가 뽑히면 모든 플레이어는 자신의 지도를 다른 플레이어에게 전달합니다. 그런 다음 상대방 보드에 이 괴물 모양을 그립니다. 이 괴물을 그리는 데 관한 다른 모든 규칙은 여전히 적용됩니다. 플레이어는 몬스터 옆의 빈 공간마다 점수를 잃습니다. 그 후, 이 괴물 카드는 게임에서 제거됩니다(그러나 발견되지 않으면 다음 시즌 동안 덱에 남아 있습니다).
덱에는 Rift Lands 카드가 1장 있습니다. 리프트 랜드(Rift Lands) 카드를 뽑으면 모든 플레이어는 자신의 보드 어디에든 지형 유형에 관계없이 1x1 정사각형을 그립니다.
===라운드 종료===
각 라운드가 끝나면 4개의 점수 카드 중 2개가 결정됩니다.
봄은 8시간 단위로 지속되며 플레이어는 카드 A와 B를 득점합니다.
여름은 8시간 단위로 지속되며 플레이어는 카드 B와 C에 점수를 매깁니다.
가을은 7시간 단위로 지속되며 플레이어는 카드 C와 D를 득점합니다.
겨울은 6시간 단위로 지속되며 플레이어는 카드 D와 A를 기록합니다.
또한 매 라운드마다 플레이어는 자신이 보유한 금화당 1점을 얻고, 몬스터 옆의 빈 공간마다 1점을 잃습니다.
점수를 매긴 후 조경 데크를 다시 섞습니다.
Winter의 점수가 나오면 게임이 종료되고 가장 많은 점수를 얻은 플레이어가 승리합니다!
-----------------------------------------
===OVERVIEW===
Cartographers is a flip-and-write game in which each of the players are separately drawing a map of their land. Each round, you'll add a feature to your map, and after a few rounds, you'll score based on the presence or arrangement of these features. The player with the most points at the end of four rounds wins the game!
===GAME COMPONENTS===
Each player has a map. This map starts mostly blank, but may have mountains, ruins, and wasteland spaces already included.
The table as a whole contains four scoring cards, labeled A through D. These take a specific format:
One of these cards looks for village spaces
One of these cards looks for forest spaces
One of these cards looks for water and farm spaces
One of these cards looks at the whole map, usually around filling certain segments of it with anything at all.
It also contains season cards, which say which two of these cards will be scored at the end of the round and how many cards will be flipped in the round:
Spring lasts 8 time units, and players score cards A and B.
Summer lasts 8 time units, and players score cards B and C.
Autumn lasts 7 time units, and players score cards C and D.
Winter lasts 6 time units, and players score cards D and A.
In addition, the table contains the deck of cards used to draw various landscapes.
===WHAT TO DO ON YOUR TURN===
The top card of the landscape deck is flipped, and all players simultaneously draw that somewhere on the map. These cards usually contain a choice to do two different terrain types in the same shape, or one specific terrain in one of two shapes. These shapes can be flipped or rotated in any 90 degree increment, and can be placed anywhere on the map - it does not need to be adjacent to anything. These shapes can't hang off the edge of the map, nor can they overlap any filled space.
If any player can't draw a particular shape, they instead draw a single 1x1 square of any terrain type anywhere on their board.
Some smaller shapes contain a gold coin. If you draw that shape, cross off a coin on the side of your map. This will be worth 1 point each scoring phase. You can also earn coins by filling all four spaces adjacent to a mountain space on your board.
Each of these cards has a number on the top left corner indicating how much time has passed. If the sum of all cards played this way is greater than or equal to the number on the season card, the round ends after all players have drawn this shape. Otherwise, start the next turn.
===SPECIAL CARDS===
There are two Ruins cards in the deck. If the Ruins card is drawn, the next shape must overlap with one of the ruins spaces on your board. All other rules about drawing this shape still apply.
There is one Monster card added to the deck each season. If a Monster card is drawn, all players pass their maps to another player. Then draw this monster shape on your opponent's board. All other rules about drawing this monster still apply. Players will lose points for each empty space next to monsters. Afterwards, this Monster card is removed from play (but if it's never found, it remains in the deck for the next season).
There is one Rift Lands card in the deck. If a Rift Lands card is drawn, all players draw a 1x1 square of any terrain type anywhere on their board.
===END OF A ROUND===
At the end of each round, two of the four scoring cards will be resolved.
Spring lasts 8 time units, and players score cards A and B.
Summer lasts 8 time units, and players score cards B and C.
Autumn lasts 7 time units, and players score cards C and D.
Winter lasts 6 time units, and players score cards D and A.
In addition to this, every round players score 1 point for each gold coin they have, and lose 1 point for each empty space next to monsters.
After scoring, the landscape deck is reshuffled.
Once Winter is scored, the game ends, and the player with the most points wins!
276e425d39f8ce119d3028d98bf6d570f097f0c7
Gamehelpmascarade
0
296
1625
2024-07-02T13:35:33Z
Moonyo
7890
새 문서: ===Gameplay=== Choose a scenario or randomly draw one to play. The other masks are removed from the game. Each player takes 6 coins and a mask. The remaining coins and masks, depending on player count, are placed in the middle. The justice board starts empty. After everyone has read and remembered all the masks, turn them face down. On your turn, take an action from view, exchange or announce. If you choose to view, secretly look at your mask. If you choose to exchange, take yo...
wikitext
text/x-wiki
===Gameplay===
Choose a scenario or randomly draw one to play. The other masks are removed from the game.
Each player takes 6 coins and a mask. The remaining coins and masks, depending on player count, are placed in the middle. The justice board starts empty.
After everyone has read and remembered all the masks, turn them face down.
On your turn, take an action from view, exchange or announce.
If you choose to view, secretly look at your mask.
If you choose to exchange, take your mask with another's and exchange or pretend to exchange them.
If you choose to announce, declare the name of the mask you think you have. All other players may challenge. If nobody challenges, apply its power without revealing. Otherwise, reveal the mask of all players involved. The actual owners apply the effect (even out of turn) and all other players pay 1 coin and place them on the justice board. You cannot do this action if you are forced to reveal your mask during the last player's turn.
The first four turns must be exchange. Afterwards, any action may be taken. Play proceeds clockwise (i.e. the player on your left takes the next turn when sitting in a circle).
===End of the Game===
If you have 13 coins, you immediately win.
If someone runs out of money, the richest player wins.
You can also win with the cheater if you have 10 or more coins.
===Mask Powers===
Beggar: Demand a coin starting from the player to your left. If they have more coins than you, they must give you one.
Cheater: If you have 10 or more coins, you immediately win the game.
Empress: Take 3 coins from the bank.
Fool: Take 1 coin and perform the exchange action with any 2 players.
Guru: Choose another player. They must announce their mask, then reveal their card. If they are wrong, they must pay 4 coins to you.
Judge: Take all the coins from the justice board. Fines are paid afterwards.
King: Take 2 coins from the bank.
Patron: Take 3 coins from the bank. Your neighbors take 1 coin each.
Peasant (x2): Take 1 coin from the bank. If two peasants are revealed, take 1 extra coin.
Princess: Take 2 coins from the bank. Choose another player who must reveal their card to everyone but themselves.
Puppeteer: Choose 2 players and take 1 coin from each of them. They must switch masks and coins.
Sorceress: Exchange your coins with a player of your choice. Fines are paid afterwards.
Spy: View your card and another player’s and perform the exchange action with them.
Thief: Take 1 coin from each of your neighbors.
Trickster: Take 2 coins from the richest opponent. Choose if tied.
Widow: Take coins until you have at least 10.
==Variants===
Script: You can choose from standard, advanced and custom.
Log masks: You can choose whether masks are logged.
Custom scripts have these requirements:
The judge must be in play.
At least one-third of the masks must bring money into play.
Both or neither peasants must be included.
Certain masks have player requirements.
At most 2 cards are in the center.
8d1fd2f03d1b07df608a619034ced897371ffa03
1626
1625
2024-07-02T15:15:05Z
Moonyo
7890
wikitext
text/x-wiki
===게임 플레이===
시나리오를 선택하거나 무작위로 하나를 뽑아 플레이하세요. 다른 마스크는 게임에서 제거됩니다.
각 플레이어는 6개의 동전과 마스크를 가져갑니다. 플레이어 수에 따라 남은 동전과 마스크는 중앙에 배치됩니다. 사법판은 비어 있기 시작합니다.
모두가 마스크를 모두 읽고 기억한 후 뒤집어 놓습니다.
자신의 차례가 되면 보기, 교환, 발표 등의 작업을 수행합니다.
보기로 결정했다면 비밀리에 마스크를 살펴보세요.
교환할 경우에는 다른 사람의 마스크와 함께 가져가서 교환하거나 교환하는 척하세요.
발표하기로 결정했다면 자신이 가지고 있다고 생각하는 마스크의 이름을 선언하세요. 다른 모든 플레이어는 도전할 수 있습니다. 아무도 도전하지 않으면 공개하지 않고 그 힘을 적용하십시오. 그렇지 않으면 관련된 모든 플레이어의 마스크를 공개합니다. 실제 소유자는 효과를 적용하고(순번이 아니더라도) 다른 모든 플레이어는 동전 1개를 지불하고 정의 보드에 놓습니다. 마지막 플레이어의 턴에 마스크를 공개해야 한다면 이 작업을 수행할 수 없습니다.
처음 4턴은 교환해야 합니다. 그 후에는 어떤 조치라도 취해질 수 있습니다. 플레이는 시계 방향으로 진행됩니다(즉, 원 안에 앉아 왼쪽에 있는 플레이어가 다음 차례를 진행합니다).
===게임 종료===
13개의 코인이 있으면 즉시 승리합니다.
누군가 돈이 떨어지면 가장 부유한 플레이어가 승리합니다.
코인이 10개 이상 있으면 치터로 승리할 수도 있습니다.
===마스크 파워===
거지: 왼쪽 플레이어부터 동전을 요구합니다. 그들이 당신보다 동전을 더 많이 갖고 있다면, 당신에게 하나를 주어야 합니다.
사기꾼: 코인이 10개 이상 있으면 즉시 게임에서 승리합니다.
황후: 은행에서 동전 3개를 가져옵니다.
바보: 동전 1개를 가져와 아무 2명의 플레이어와 교환 작업을 수행합니다.
전문가: 다른 플레이어를 선택하세요. 마스크를 공개한 다음 카드를 공개해야 합니다. 그들이 틀렸다면 그들은 당신에게 4코인을 지불해야 합니다.
판사: 사법판에서 모든 동전을 가져옵니다. 벌금은 나중에 지불됩니다.
왕: 은행에서 동전 2개를 가져옵니다.
후원자: 은행에서 동전 3개를 가져옵니다. 이웃은 각각 1개의 동전을 받습니다.
농민(x2): 은행에서 동전 1개를 가져옵니다. 농민 2명이 공개되면 코인 1개를 추가로 가져옵니다.
공주: 은행에서 동전 2개를 가져옵니다. 자신을 제외한 모든 사람에게 자신의 카드를 공개해야 하는 다른 플레이어를 선택하세요.
인형극: 2명의 플레이어를 선택하고 각 플레이어로부터 동전 1개를 가져옵니다. 마스크와 동전을 바꿔야 합니다.
마법사: 원하는 플레이어와 코인을 교환하세요. 벌금은 나중에 지불됩니다.
스파이: 당신의 카드와 다른 플레이어의 카드를 보고 그들과 교환 작업을 수행합니다.
도둑: 이웃으로부터 동전 1개씩 가져가세요.
사기꾼: 가장 부유한 상대에게서 동전 2개를 가져옵니다. 묶인 경우 선택하세요.
미망인: 최소 10개가 될 때까지 동전을 가져가세요.
===변형===
스크립트: 표준, 고급, 사용자 정의 중에서 선택할 수 있습니다.
마스크 로그: 마스크 기록 여부를 선택할 수 있습니다.
사용자 정의 스크립트에는 다음과 같은 요구 사항이 있습니다.
판사가 경기에 임해야 합니다.
마스크의 최소 3분의 1은 돈을 벌어야 합니다.
농민이 모두 포함되거나 포함되지 않아야 합니다.
특정 마스크에는 플레이어 요구 사항이 있습니다.
최대 2장의 카드가 중앙에 있습니다.
--------------------------------------------------------------------------
===Gameplay===
Choose a scenario or randomly draw one to play. The other masks are removed from the game.
Each player takes 6 coins and a mask. The remaining coins and masks, depending on player count, are placed in the middle. The justice board starts empty.
After everyone has read and remembered all the masks, turn them face down.
On your turn, take an action from view, exchange or announce.
If you choose to view, secretly look at your mask.
If you choose to exchange, take your mask with another's and exchange or pretend to exchange them.
If you choose to announce, declare the name of the mask you think you have. All other players may challenge. If nobody challenges, apply its power without revealing. Otherwise, reveal the mask of all players involved. The actual owners apply the effect (even out of turn) and all other players pay 1 coin and place them on the justice board. You cannot do this action if you are forced to reveal your mask during the last player's turn.
The first four turns must be exchange. Afterwards, any action may be taken. Play proceeds clockwise (i.e. the player on your left takes the next turn when sitting in a circle).
===End of the Game===
If you have 13 coins, you immediately win.
If someone runs out of money, the richest player wins.
You can also win with the cheater if you have 10 or more coins.
===Mask Powers===
Beggar: Demand a coin starting from the player to your left. If they have more coins than you, they must give you one.
Cheater: If you have 10 or more coins, you immediately win the game.
Empress: Take 3 coins from the bank.
Fool: Take 1 coin and perform the exchange action with any 2 players.
Guru: Choose another player. They must announce their mask, then reveal their card. If they are wrong, they must pay 4 coins to you.
Judge: Take all the coins from the justice board. Fines are paid afterwards.
King: Take 2 coins from the bank.
Patron: Take 3 coins from the bank. Your neighbors take 1 coin each.
Peasant (x2): Take 1 coin from the bank. If two peasants are revealed, take 1 extra coin.
Princess: Take 2 coins from the bank. Choose another player who must reveal their card to everyone but themselves.
Puppeteer: Choose 2 players and take 1 coin from each of them. They must switch masks and coins.
Sorceress: Exchange your coins with a player of your choice. Fines are paid afterwards.
Spy: View your card and another player’s and perform the exchange action with them.
Thief: Take 1 coin from each of your neighbors.
Trickster: Take 2 coins from the richest opponent. Choose if tied.
Widow: Take coins until you have at least 10.
==Variants===
Script: You can choose from standard, advanced and custom.
Log masks: You can choose whether masks are logged.
Custom scripts have these requirements:
The judge must be in play.
At least one-third of the masks must bring money into play.
Both or neither peasants must be included.
Certain masks have player requirements.
At most 2 cards are in the center.
1a53e0ca28e0b1ea2c8d6fd453f4b4d65f69eade
Tips carcassonne
0
297
1630
2024-07-10T02:51:27Z
Greenpin
9832
파파고 번역후 이해하기 쉽게 수정함.
wikitext
text/x-wiki
[기본 게임]
게임의 가장 큰 부분은 상대가 도시(또는 도로)를 만드는 것을 방해하고 상대가 당신의 것을 훔치는 것을 막는 것입니다.
기본 게임에는 상당히 제한된 타일 세트가 있기 때문에 적의 미플(말)을 차단하는 것이 매우 쉽습니다.
단 한 명의 미플만 있는 도시는 도둑맞기 쉽고, 여러 명의 미플이 있는 도시는 막히기 쉽습니다. 만약 여러분의 도시가 완성하는 것이 불가능해지면, 여러분의 미플은 그곳에 갇히게 되는데, 이것은 큰 핸디캡입니다.
이러한 이유로 거대 도시를 건설하는 것을 피하고 대신 몇 개의 작은 도시를 선택하고 상대에게 공격하는 것이 나을 때가 많습니다.
또한 한 번에 너무 많은 미플을 사용하지 않도록 합니다(예: 3개의 다른 도시를 건설하는 경우 도시/도로를 마무리하는 데 집중해야 함).
사실, 마지막 몇 개의 타일이 있을 때까지 항상 최소 1미플을 손에 쥐도록 노력해야 합니다.
더 작은 기기에서 게임을 한다면, 여러분이 실제로 그것을 배치하고 싶었던 장소를 "놓치지" 않도록 여러분의 미플을 배치하는 곳을 조심하세요. 확정하기 전에 먼저 화면을 잘 키우거나 줄여 보세요.
[상인과 건축가]
가능한 한 빨리 그리고 자주 건축가를 사용해야 합니다. 건축가가 상대방에게 갇힐 수 있는 취약한 경우에만 사용하지 마십시오.
가능한 한 자주 도시를 건설하는 데 집중하세요. 도로는 기본 게임에서 이미 상당히 약하지만, 확장과 도시에서 사용할 수 있는 "자원"으로 인해 훨씬 더 생산성이 떨어집니다.
같은 이유로, 수도원이나 수도원에 항상 사람을 보낼 가치가 있는 것은 아닙니다. 정말로 그 돈을 돌려받을 수 있을까요? 그 위험은 단지 7점 혹은 8점 정도의 가치가 있을까요?
(물론 맨 끝을 제외하고) 큰 미플을 들판에서 낭비하지 마세요. 도시를 공격하거나 방어하기 위해, 그것은 특히 소중합니다.
또한, 분명 큰 미플이 갇히지 않는 것이 매우 중요합니다. 일반 미플을 잃는 것보다 훨씬 더 불편하죠.
9188dd0f9eae1eebab0925bde756a07f51e7afe1
Gamehelpthelast
0
298
1633
2024-08-20T05:42:43Z
Notsogood
10001
새 문서: ## 게임 목표 * **가능한 적은 점수**를 얻으면서 상대방이 **원하지 않는 카드**를 받도록 만드세요! ## 라운드 준비 * 1부터 12까지의 숫자 카드 4가지 색깔 총 48장을 섞습니다. * **3인 플레이:** 각 플레이어에게 카드 12장씩 나눠줍니다. * **4인 플레이:** 각 플레이어에게 카드 9장씩 나눠줍니다. * **5인 플레이:** 각 플레이어에게 카드 8장씩 나눠줍니다. * 남은 카드들...
wikitext
text/x-wiki
## 게임 목표
* **가능한 적은 점수**를 얻으면서 상대방이 **원하지 않는 카드**를 받도록 만드세요!
## 라운드 준비
* 1부터 12까지의 숫자 카드 4가지 색깔 총 48장을 섞습니다.
* **3인 플레이:** 각 플레이어에게 카드 12장씩 나눠줍니다.
* **4인 플레이:** 각 플레이어에게 카드 9장씩 나눠줍니다.
* **5인 플레이:** 각 플레이어에게 카드 8장씩 나눠줍니다.
* 남은 카드들은 점수 더미를 형성합니다.
* 첫 번째 트릭의 첫 번째 플레이어는 무작위로 결정됩니다.
## 트릭 플레이
* 점수 더미의 첫 번째 카드를 뒤집어 놓습니다.
* 첫 번째 플레이어가 한 장의 카드를 냅니다.
* 시계 방향으로, 마지막 플레이어를 제외한 모든 플레이어는 첫 번째 플레이어가 선택한 색깔의 카드를 내야 합니다. 해당 색깔의 카드가 없다면 어떤 카드든 낼 수 있습니다.
* 하지만 마지막 플레이어는 트릭 중에 이미 나온 색깔 중 하나를 낼 수 있습니다. 이러한 색깔의 카드가 없다면 원하는 카드를 낼 수 있습니다.
* 모든 경우에, 자신의 카드 색깔이 승리하는 색깔이 됩니다. 따라서 마지막 플레이어가 나온 색깔 중 하나를 따라할 수 없다면 마지막 플레이어가 트릭을 가져갑니다.
* 트릭의 마지막 플레이어가 낸 카드 중 가장 높은 숫자의 카드를 가진 플레이어가 트릭 시작 시에 공개된 점수 더미에서 카드를 가져갑니다.
* 해당 플레이어는 다음 중 하나를 선택할 수 있습니다.
* 카드를 뒤집어서 자신의 옆에 놓습니다.
* 카드를 자신의 손에 넣고, 대신 자신의 손에서 한 장의 카드를 뽑아 뒤집어서 자신의 옆에 놓습니다.
* 모든 플레이된 카드는 버려지고, 트릭의 승자가 다음 트릭의 첫 번째 플레이어가 됩니다.
## 라운드 점수 계산
* 모든 카드가 플레이되면 라운드가 끝납니다.
* 각 플레이어는 자신의 옆에 뒤집어 놓은 카드의 합계를 더해 동일한 페널티 점수를 얻습니다.
* 가장 낮은 페널티 점수를 가진 플레이어가 승리합니다!
## 2인 플레이 변형
* 각 플레이어에게 카드 12장씩 나눠주고, 12장의 카드를 뒤집어 첫 번째 트릭의 첫 번째 플레이어 오른쪽에 놓습니다. 이것은 유령 플레이어의 더미입니다.
* 나머지 카드들은 평소와 같이 점수 더미를 형성합니다.
* 유령 플레이어는 자동으로 플레이하며, 항상 자신의 더미의 맨 위 카드를 공개합니다. 그 외에는 일반 규칙에 따라 플레이합니다.
* 유령 플레이어의 차례가 되면, 자신의 더미에서 첫 번째 카드를 내고 시계 방향으로 플레이합니다.
* 유령 플레이어가 트릭을 이기면, 점수 더미에서 카드를 자신의 앞에 놓고 새로운 트릭을 시작합니다.
* 게임이 끝나면 유령 플레이어의 점수는 계산하지 않습니다.
d6fd00d002dc241450bbedba8b11bc77da61684e
Gamehelpthermopyles
0
116
1634
785
2024-08-22T09:06:01Z
Ufm
6353
문서를 비움
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelpdigupadventure
0
299
1635
2024-10-03T14:20:21Z
Bbobbodory
10124
새 문서: 개요 각 플레이어는 9장의 카드를 뒤집어 자신의 광산을 만들고, 옆에 한 장을 따로 두어 자신이 좋아하는 색을 표시합니다. 한 플레이어가 모든 카드를 뒤집으면 게임이 종료됩니다. 카드 종류 모험 카드 (긴 설명이 있는 카드) 보석 카드 우상 카드 해골 카드 손패 제한 손패 제한은 3장입니다. 게임 진행 플레이어는 자신의 차례에 최대 두 장의 카드를 낼 수 있...
wikitext
text/x-wiki
개요
각 플레이어는 9장의 카드를 뒤집어 자신의 광산을 만들고, 옆에 한 장을 따로 두어 자신이 좋아하는 색을 표시합니다.
한 플레이어가 모든 카드를 뒤집으면 게임이 종료됩니다.
카드 종류
모험 카드 (긴 설명이 있는 카드)
보석 카드
우상 카드
해골 카드
손패 제한
손패 제한은 3장입니다.
게임 진행
플레이어는 자신의 차례에 최대 두 장의 카드를 낼 수 있습니다.
a) 모험 카드를 내고 그 효과를 적용합니다.
b) 뒤집어진 카드를 보석으로 교체합니다. 공개된 보석 카드는 손으로 가져오며, 나중에 교체할 때 사용할 수 있습니다.
c) 광산에 우상 카드가 이미 있는 경우 손에서 우상 카드를 낼 수 없습니다. 하지만 다른 카드 효과를 통해 광산에 여러 개의 우상이 놓일 수 있습니다.
턴이 끝날 때 손에 3장이 남도록 버려야 합니다. 추가로 버리는 것은 선택 사항이며, 손패는 자동으로 다시 3장으로 채워집니다.
당신의 테이블 배치는 1번에서 9번까지 번호가 매겨져 있습니다. (즉, 윗줄은 1, 2, 3번 위치, 중간줄은 4, 5, 6번, 아랫줄은 7, 8, 9번입니다.) 보석 개수가 해당 번호와 일치하는 카드를 그 위치에 놓으면 점수를 얻습니다. 예를 들어, 보석 1개가 있는 카드를 테이블 배치의 왼쪽 상단(1번 위치)에, 보석 9개가 있는 카드를 오른쪽 하단(9번 위치)에 놓고 싶어할 것입니다.
게임 종료
한 플레이어가 9장의 카드를 모두 뒤집으면 게임이 종료됩니다.
모든 플레이어가 동일한 횟수만큼 턴을 마치고, 각 플레이어는 자신의 광산에 있는 뒤집어진 카드를 모두 공개한 후 점수를 계산합니다.
게임 종료 시 점수 계산
좋아하는 색이 올바른 위치에 있을 경우 = 3점
좋아하는 색이 잘못된 위치에 있을 경우 = 2점
좋아하지 않는 색이 올바른 위치에 있을 경우 = 1점
우상 카드 = 2점
해골 카드 = 0점
점수를 합산하여 가장 높은 점수를 받은 사람이 승리합니다.
동점일 경우: 가장 많은 연속된 좋아하는 색 카드를 가진 사람이 승리합니다.
f1c2a2f03064b42248aad24815886da0f59b38cf
Gamehelpnanatoridori
0
300
1636
2024-10-19T17:13:35Z
Hyunscat
10169
새 문서: [나나토리도리] 플레이어는 얼마나 빨리 패를 모두 내보낼지 경쟁합니다. 여러 장의 카드를 한 번에 내는 것으로, 패를 빨리 다 낼 수 있습니다. 단, 한 번에 카드를 내기 위해서는 같은 숫자이고, 또한 손 안에 나란히 있어야합니다. 패에 추가한 후에는 카드를 재정렬 할 수 없습니다. 카드를 획득할 때는 전략적으로 생각하고 그것들을 패 안에 잘 배치할 필요가 있...
wikitext
text/x-wiki
[나나토리도리]
플레이어는 얼마나 빨리 패를 모두 내보낼지 경쟁합니다.
여러 장의 카드를 한 번에 내는 것으로, 패를 빨리 다 낼 수 있습니다.
단, 한 번에 카드를 내기 위해서는 같은 숫자이고, 또한 손 안에 나란히 있어야합니다.
패에 추가한 후에는 카드를 재정렬 할 수 없습니다. 카드를 획득할 때는 전략적으로 생각하고 그것들을 패 안에 잘 배치할 필요가 있습니다.
- 숫자 카드 (63장: 1~7이 9장씩)
- 펭귄 (12개: 6색 2개씩)
- 요약 카드(6장)
[게임 준비]
1) 각 플레이어는, 자신의 색깔의 펭귄 2개와 요약 카드 1장을 받습니다.
2) 숫자카드를 잘 섞고 카드 더미를 만듭니다.
3) 8장씩 패를 나눠준다.(패의 표면은 주인만 확인할 수 있습니다.)
【!】매우 중요! 이 게임에서는 패의 순서를 바꾸면 안됩니다!
4) 숫자 카드를 내는 자리와, 버림패 카드 더미 자리를 둡니다.
(버림패 카드는 항상 공개 정보로, 언제든지 확인할 수 있습니다)
5) 처음 카드를 낼 스타트 플레이어를 정하면 게임 시작!
[게임의 흐름]
스타트 플레이어부터 시계 방향 순으로 차례를 진행하며、자신의 차례에서는「A:카드를 낸다」또는「B:패스」중 하나를 선택합니다.
그리고, 패가 0장이 된 플레이어부터 생존입니다.
최후의 1인이 되지 않도록, 재빨리 모든 패를 다 털어냅시다.
A:카드를 내다.
패에서 숫자 카드를 꺼냅니다.
・자리에 카드가 없을 때는 원하는 카드를 낼 수 있다.
・패에서 '옆에 있는 똑같은 카드'는 몇 장이라도 한꺼번에 꺼낼 수 있다.
・직전에 나온 카드 보다, 강한 카드의 조합만 낼 수 있다.
(숫자가 클수록 강하다.( 1 < 7 ))
(숫자에 관계없이, 매수가 많을수록 강하다( 7이 3장 < 1이 4장))
카드를 꺼내면 자리에 나와 있던 카드를 내 패에 추가할지 버릴지 선택합니다.
「내 패에 추가한다」라면 그것들을 한데 모아, 자신의 패에서 원하는 위치에 꽂습니다.
「버리다」라면, 그것들을 버리는 버림패 더미로 옮깁니다.
B:패스
카드를 낼 수 없거나 내고 싶지 않을 때는 패스를 합니다.
카드 더미에서 1장 뽑아, 「내 패에 추가한다」인지, 「버린다」인지 선택합니다.
*전원이 패스를 하면*
내가 카드를 낸 다음, 다른 전원이 패스를 해서 다시 내 차례가 오면 자리의 카드를 모두 버립니다. 그 후, 새로운 스타트 플레이어가 되어 원하는 카드를 내고 게임을 진행합니다.
[게임의 종료]
패를 다 꺼내어 0장이 된 사람부터 생존합니다. 최후의 1인이 남으면 게임 종료입니다. 최후의 1인은 자신의 펭귄을 1개를 상자에 되돌려 놓습니다.
최후의 1인을 새로운 시작 플레이어로 삼아 새롭게 게임을 시작합니다. 펭귄이 0개가 되면 패배합니다. 그리고 그 사람을 제외한 모든 사람이 우승입니다.
ee43bcda2bfdb290877be33183d0fd1ba6c4abc6
1637
1636
2024-10-29T03:34:39Z
Ingonryu
10187
코리아보드게임즈 공식 번역에 따라 일부 문장을 다듬었습니다(by 코리아보드게임즈 한국어화팀)
wikitext
text/x-wiki
[가지각새]
모든 플레이어는 자기 손에 든 카드를 누가 먼저 전부 낼 수 있는지 경쟁합니다.
여러 장의 카드를 한 번에 내는 것으로, 손에 든 카드를 빨리 다 낼 수 있습니다.
단, 한번에 카드를 여러 장 묶어서 내려면 그 카드들이 모두 같은 숫자이며, 손 안에서 이웃해 있어야 합니다.
절대로 손에 든 카드의 순서를 바꿔선 안 됩니다. 새로 손으로 들고 온 패는, 한번 추가한 후에는 위치를 바꿀 수 없습니다. 따라서 카드를 추가할 때는, 어느 위치가 가장 좋을지 전략적으로 생각할 필요가 있습니다.
- 숫자 카드 (63장: 1~7이 9장씩)
- 펭귄 말 (12개: 6색깔 2개씩)
- 요약 카드(6장)
[게임 준비]
1) 숫자 카드 63장을 잘 섞어서 뒷면이 보이도록 카드 더미를 만듭니다.
2) 모두에게 더미의 카드를 8장씩 나눠줍니다. 각자 나눠 받은 카드를 앞면이 자기에게만 보이도록 손에 듭니다.
[!] 매우 중요! 절대로 손에 든 카드의 순서를 바꿔선 안 됩니다!
3) 테이블 중앙에 바닥(숫자 카드 내는 곳)과 버린 카드 놓는 곳으로 쓸 공간을 마련해 둡니다.
4) 각자 색깔을 하나씩 골라서, 그 색깔의 펭귄 말 2개를 가져가고 요약 카드 1장을 받습니다.
5) 처음 카드를 낼 시작 플레이어를 정하고 게임을 시작합니다.
[게임 방법]
게임은 여러 라운드에 걸쳐 진행되며, 차례는 시계 방향으로 돌아갑니다. 자기 차례가 되면 "A: 카드 내기" 또는 "B: 패스" 중 하나를 골라서 수행합니다.
우선 시작 플레이어의 "카드 내기"를 통해 라운드가 시작되며, 이후 손에 든 카드 수가 0장이 된 사람들이 차례차례 라운드에서 빠져나가는 방식으로 게임이 진행됩니다.
꼴찌가 되지 않도록 남들보다 빠르게 손에 든 카드를 전부 내버립시다.
A: 카드 내기
손에 든 숫자 카드를 앞면이 보이도록 바닥에 냅니다.
・바닥에 카드가 없을 때는 원하는 카드를 낼 수 있습니다.
・숫자가 같은 카드끼리 손 안에서 이웃해 있다면, 그 카드들끼리 원하는 만큼 묶어서 한꺼번에 낼 수 있습니다.
・직전에 바닥에 나온 카드 것보다 강한 조합의 카드를 내야 합니다.
・숫자가 클수록 강합니다(1 < 7).
・숫자에 관계없이, 카드 장수가 많을수록 강합니다("7" 세 장 < "1" 네 장).
직전에 바닥에 나온 카드를 자기 손으로 들고 올지, 버릴지를 선택합니다.
손에 들기로 했다면, 직전에 바닥에 나온 카드를 한데 묶어서, 자기 손에 든 카드의 원하는 위치에 끼워 넣습니다(다른 카드 사이 또는 양쪽 끝).
버리기로 했다면, 그 카드들을 버린 카드 놓는 곳으로 옮깁니다.
B: 패스
카드를 낼 수 없거나, 내고 싶지 않다면 패스합니다.
더미에서 카드를 1장 뽑아서 앞면을 본 뒤, 그 카드를 손으로 들고 올지, 아니면 버릴지를 선택합니다.
*모두가 패스한 경우*
내가 카드를 낸 뒤에, 나머지 사람들이 모두 패스를 선언하여 다시 내 사람에게 차례가 돌아올 경우, 바닥에 놓인 카드를 모두 버립니다. 그 후, 내가 새로운 시작 플레이어가 되어, 원하는 카드를 내면서 라운드를 계속 이어갑니다.
[게임 종료]
카드를 전부 내서 손에 든 카드가 0장이 된 사람은 이번 라운드에서 빠집니다. 나머지 사람들은 라운드를 계속 이어갑니다. 그러다가 남은 사람이 1명밖에 없게 되는 순간, 라운드가 종료됩니다. 마지막까지 남은 사람은 자기 펭귄 말 1개를 상자에 넣습니다.
이렇게 자기 펭귄 말을 잃은 사람이 새로운 시작 플레이어가 되어, 새로운 라운드를 시작합니다. 펭귄 말이 0개가 된 사람이 나오면, 게임이 완전히 종료되고 그 사람이 패배합니다. 나머지 사람들은 모두 승리합니다.
d5d6a2519d382c8f022b3650af9f0c3bdc7e0b8a
Gamehelpcosmoctopus
0
301
1638
2024-10-31T16:48:37Z
Wz0ol
10196
문어를 움직이고, 기호에 따라서 카드를 사용하며 최대 8장의 카드를 가지고 있을 수 있습니다. 그 후엔 다음 사람의 차례로 넘어가게 됩니다.
wikitext
text/x-wiki
게임 목표:
가장 먼저 문어의 8개 다리를 얻으세요
게임 방법:
문어를 움직이고, 기호에 따라서 카드를 사용하며 최대 8장의 카드를 가지고 있을 수 있습니다. 그 후엔 다음 사람의 차례로 넘어가게 됩니다..
자세한 설명:
1. 원하는 곳으로 문어를 움직이고 도착한 곳에서 얻을 수 있는 보너스(자원)를 받으세요. 그러나 움직일 때 각 공간에 도착하게 된 경우에는 자원을 지불해야 하고, 마지막으로 도착한 공간에서만 자원을 얻어갈 수 있습니다.
2. 당신이 가지고 있는 카드 중 사용하고 싶은 카드를 선택하세요. 전에 사용한 효과로 인해 더 많은 카드를 사용하게 될 수도 있지만, 보통 1개의 카드만을 사용할 수 있습니다. 카드를 사용하기 위해선 각 카드가 가진 비용을 지불할 수 있어야 하며 대부분의 카드들은 카드의 윗부분에 필요한 금액과 자원들이 적혀있습니다. 손에 있는 카드의 수를 줄일 수 있습니다. 각 색의 카드들은 같은 색의 자원들과 같은 역할을 하게 됩니다. 예) 빨간색 카드는 빨간 자원 역할을 하게 됩니다.
3. 가지고 있는 카드가 8개를 넘고, 모두 다른 카드인지 확인하세요. 게임이 끝나기 전에 8개 이상의 카드가 생겼을 경우에는 자원으로 바꾸세요.
4. 운이 없게도 자원 13개를 얻게 되면, 해당된 자원과 관련된 금지된 지식을 얻고 자원을 모두 버리고 다리 두개를 얻어가세요.
5. 첫번째 다리를 얻게된다면, 바닥에 깔려있는 카드 중 하나를 가지게 될 수 있습니다.
b6914c2e398d46783f47b1f145ff0680eea0ebae
1640
1638
2024-10-31T17:07:22Z
Wz0ol
10196
wikitext
text/x-wiki
게임 목표:
가장 먼저 문어의 8개 다리를 얻으세요
게임 방법:
문어를 움직이고, 기호에 따라서 카드를 사용하며 최대 8장의 카드를 가지고 있을 수 있습니다. 그 후엔 다음 사람의 차례로 넘어가게 됩니다.
자세한 설명:
# 원하는 곳으로 문어를 움직이고 도착한 곳에서 얻을 수 있는 보너스(자원)를 받으세요. 그러나 움직일 때 각 공간에 도착하게 된 경우에는 자원을 지불해야 하고, 마지막으로 도착한 공간에서만 자원을 얻어갈 수 있습니다.
# 당신이 가지고 있는 카드 중 사용하고 싶은 카드를 선택하세요. 전에 사용한 효과로 인해 더 많은 카드를 사용하게 될 수도 있지만, 보통 1개의 카드만을 사용할 수 있습니다. 카드를 사용하기 위해선 각 카드가 가진 비용을 지불할 수 있어야 하며 대부분의 카드들은 카드의 윗부분에 필요한 금액과 자원들이 적혀있습니다. 개인 공간에 있는 카드의 수를 줄일 수 있습니다. 각 색의 카드들은 같은 색의 자원들과 같은 역할을 하게 됩니다. 예) 빨간색 카드는 빨간 자원 역할을 하게 됩니다.
# 개인 공간에 있는 카드가 8개를 넘고, 모두 다른 카드인지 확인하세요. 게임이 끝나기 전에 8개 이상의 카드가 생겼을 경우에는 자원으로 바꾸세요.
# 운이 없게도 자원 13개를 얻게 되면, 해당된 자원과 관련된 금지된 지식을 얻고 자원을 모두 버리고 다리 두 개를 얻어가세요.
# 첫 번째 다리를 얻게 된다면, 바닥에 깔려있는 카드 중 하나를 가지게 될 수 있습니다.
9083a0c6f63b39d3e69ec7959d1f861c92097886
1641
1640
2024-11-01T12:52:20Z
Sikpang9
10195
wikitext
text/x-wiki
게임 목표:
가장 먼저 문어의 8개 다리를 얻으세요
게임 방법:
문어를 움직이고, 기호에 따라서 카드를 사용하며 최대 8장의 카드를 가지고 있을 수 있습니다. 그 후엔 다음 사람의 차례로 넘어가게 됩니다.
자세한 설명:
1. 원하는 곳으로 문어를 움직이고 도착한 곳에서 얻을 수 있는 보너스(자원)를 받으세요. 그러나 움직일 때 각 공간에 도착하게 된 경우에는 자원을 지불해야 하고, 마지막으로 도착한 공간에서만 자원을 얻어갈 수 있습니다.
2. 당신이 가지고 있는 카드 중 사용하고 싶은 카드를 선택하세요. 전에 사용한 효과로 인해 더 많은 카드를 사용하게 될 수도 있지만, 보통 1개의 카드만을 사용할 수 있습니다. 카드를 사용하기 위해선 각 카드가 가진 비용을 지불할 수 있어야 하며 대부분의 카드들은 카드의 윗부분에 필요한 금액과 자원들이 적혀있습니다. 개인 공간에 있는 카드의 수를 줄일 수 있습니다. 각 색의 카드들은 같은 색의 자원들과 같은 역할을 하게 됩니다. 예) 빨간색 카드는 빨간 자원 역할을 하게 됩니다.
3. 개인 공간에 있는 카드가 8개를 넘고, 모두 다른 카드인지 확인하세요. 게임이 끝나기 전에 8개 이상의 카드가 생겼을 경우에는 자원으로 바꾸세요.
4. 운이 없게도 자원 13개를 얻게 되면, 해당된 자원과 관련된 금지된 지식을 얻고 자원을 모두 버리고 다리 두 개를 얻어가세요.
5. 첫 번째 다리를 얻게 된다면, 바닥에 깔려있는 카드 중 하나를 가지게 될 수 있습니다.
1da60c72104569f125b1f4f40c413308ce206550
Tips cosmoctopus
0
302
1639
2024-10-31T16:52:34Z
Sikpang9
10195
새 문서: 가장 먼저 문어의 8개 다리를 얻으세요 게임 방법 문어를 움직이고, 기호에 따라서 카드를 사용하며 최대 8장의 카드를 가지고 있을 수 있습니다. 그 후엔 다음 사람의 차례로 넘어가게 됩니다. 자세한 설명 1. 원하는 곳으로 문어를 움직이고 도착한 곳에서 얻을 수 있는 보너스(자원)를 받으세요. 그러나 움직일 때 각 공간에 도착하게 된 경우에는 자원을 지불해...
wikitext
text/x-wiki
가장 먼저 문어의 8개 다리를 얻으세요
게임 방법
문어를 움직이고, 기호에 따라서 카드를 사용하며 최대 8장의 카드를 가지고 있을 수 있습니다. 그 후엔 다음 사람의 차례로 넘어가게 됩니다.
자세한 설명
1. 원하는 곳으로 문어를 움직이고 도착한 곳에서 얻을 수 있는 보너스(자원)를 받으세요. 그러나 움직일 때 각 공간에 도착하게 된 경우에는 자원을 지불해야 하고, 마지막으로 도착한 공간에서만 자원을 얻어갈 수 있습니다.
2. 당신이 가지고 있는 카드 중 사용하고 싶은 카드를 선택하세요. 전에 사용한 효과로 인해 더 많은 카드를 사용하게 될 수도 있지만, 보통 1개의 카드만을 사용할 수 있습니다. 카드를 사용하기 위해선 각 카드가 가진 비용을 지불할 수 있어야 하며 대부분의 카드들은 카드의 윗부분에 필요한 금액과 자원들이 적혀있습니다. 손에 있는 카드의 수를 줄일 수 있습니다. 각 색의 카드들은 같은 색의 자원들과 같은 역할을 하게 됩니다. 예) 빨간색 카드는 빨간 자원 역할을 하게 됩니다.
3. 가지고 있는 카드가 8개를 넘고, 모두 다른 카드인지 확인하세요. 게임이 끝나기 전에 8개 이상의 카드가 생겼을 경우에는 자원으로 바꾸세요.
4. 운이 없게도 자원 13개를 얻게 되면, 해당된 자원과 관련된 금지된 지식을 얻고 자원을 모두 버리고 다리 두개를 얻어가세요.
5. 첫번째 다리를 얻게된다면, 바닥에 깔려있는 카드 중 하나를 가지게 될 수 있습니다.
9195056bccb530f2c11181f71aa59ce09dc5ad33
Tips hearts
0
201
1642
1306
2024-11-01T15:00:17Z
Blobugh
8198
wikitext
text/x-wiki
달 촬영(26점 모두 획득):
카드가 있는 경우에만 달을 쏘려고 합니다. 높은 카드를 갖는 것이 도움이 되지만, 그것보다 더 많은 것이 있습니다. 첫째, 한 벌을 많이 갖는 것이 좋습니다. 왜냐하면 그 소송의 몇 라운드가 인도되고 나면 다른 사람들이 모두 소진되고 아무도 당신에게서 주도권을 빼앗지 않고 그 소송으로 인도할 수 있기 때문입니다. 비록 낮은 카드일지라도. 실패하더라도 아무도 그 소송을 이끌지 않을 것이기 때문에 너무 많은 카드를 가져갈까 걱정할 필요가 없기 때문에 이것은 또한 좋습니다.
하트 카드가 낮고 달을 쏘고 싶다면 교환하십시오. 거래 세션이 끝났을 때 누군가가 당신보다 높은 하트를 가지고 있다면 달을 쏘려고 하지 마십시오. 유일한 예외는 다른 사람보다 높은 하트를 충분히 가지고 있어서 낮은 하트를 내기 전에 모두 고갈될 가능성이 있다는 것입니다.
다른 사람들이 달을 쏘는 것을 막는 것:
달을 쏘려고 하는 사람들을 조심하세요. 대부분의 경우 이러한 상황은 손 시작 시 왼쪽으로 전달하는 세 장의 카드 중 하나가 손에 들고 있는 카드보다 하트가 낮은 카드인지 확인함으로써 피할 수 있습니다. 이런 식으로 하트 트릭을 하고 4점만 얻으면 항상 달을 멈출 수 있습니다. 특정 문양이 4~5개 이상 있는 경우 자신이 점수를 얻거나 다른 두 명 이상의 플레이어가 점수를 받을 때까지 가장 높은 수트를 플레이할 때까지 기다리십시오. 점수를 얻지 않고 해당 슈트를 플레이할 수 있다면 두 번째로 높은 슈트를 플레이하십시오. 그렇게하면 자신을 나쁜 상황에 빠뜨리지 않고 가장 높은 카드로 달을 막을 수 있습니다.
첫 번째 트릭:
여기에는 많은 옵션이 없습니다. 클럽 2가 있다면 당신이 그것을 이끌고 있는 것입니다. 첫 번째 트릭에서는 점수가 떨어질 수 없으므로 최대한 높은 클럽을 내십시오. 클럽이 없는 경우 다른 위험한 높은 카드(예: 스페이드 A 또는 K)를 내거나 두 번째 소송에서 자신을 무효화할 기회를 사용하십시오. 더 많은 공백은 나중에 더 많은 기회를 의미합니다.
블리딩 스페이드:
일반적으로 말해서 첫 번째 트릭이 실패한 후 스페이드 Q를 차지할 위험이 없는 플레이어는 가능한 한 스페이드를 앞서고 싶어할 것입니다. 이 이면의 주요 이론은 간단합니다. 스페이드가 계속 리드되면 A, K 및 Q를 가진 플레이어가 결국에는 스페이드를 플레이해야 합니다. 만약 당신이 그 카드들을 가지고 있지 않다면, 당신은 그것들을 가능한 한 빨리 플레이하도록 하고 싶어, 그래서 다른 누군가는 그 13포인트에 갇히게 될 것입니다. 스페이드 출혈에 실패하면 퀸을 들고 있는 플레이어가 다른 슈트(예: 클럽 또는 다이아몬드)에 빈 공간을 만든 다음 퀸을 오프 슈트 트릭으로 버릴 수 있습니다. 트릭을 이길 가능성이 높은 카드가 없는 거의 완벽한 핸드를 들고 있지 않는 한, 여왕이 다른 사람에게 떨어질 때까지 전투 계획에는 가능한 한 많은 스페이드를 이끄는 것이 포함되어야 합니다.
블리딩 스페이드의 예외:
여기에는 예외가 있습니다. 13점 이하의 다른 플레이어가 있고 게임을 끝내고 싶지 않다면 그가 가지고 있으면 강제로 게임을 하고 싶지 않으므로 먼저 누가 그것을 가지고 있는지 알아내십시오. 이기고 있는 플레이어가 그것을 가지고 있다면, 반드시 출혈을 일으키고, 지는 플레이어가 그것을 가지고 있다면, 그가 준비가 되었을 때 플레이할 수 있도록 먼저 보이드를 가져오도록 하십시오. 그는 아마도 이기고 있는 플레이어에게 게임을 시도할 것입니다. 누가 가지고 있는지 알 수 없더라도 리드를 가진 플레이어가 아닐 확률이 3분의 2이기 때문에 스페이드를 흘리지 않는 것이 좋습니다. 리드와 함께 플레이어에게 여왕. 누가 스페이드의 여왕을 가지고 있는지 알아내는 몇 가지 방법이 있습니다. 첫째, 스페이드가 이끄는 라운드에서 스페이드가 아닌 플레이를 하는 사람을 확실히 제거할 수 있습니다. 여왕이 있으면 하지 않을 것이기 때문에 삽으로 리드하는 사람을 제거할 수도 있습니다. 마지막으로, 누군가가 높은 클럽이나 다이아몬드로 선두를 달리고 있고 그 슈트를 이미 한 두 번 이상 연주했다면 아마도 여왕이 있거나 달을 쏘려고 한다는 의미일 것입니다. 위험한 움직임.
방어 스페이드:
반대로, 방어되지 않은 Q, K 또는 A 스페이드에 갇힌 경우 스페이드가 계속 이끌리면 퀸을 가져갈 위험이 있습니다. 당신의 목표는 카드가 한두 장 밖에 없는 수트를 이끌고 가능한 한 빨리 공백을 만드는 것이어야 합니다. 예를 들어, 다이아몬드 두 개만 버리면 다른 사람이 다이아몬드를 이끌고 당신이 나쁜 스페이드를 떨어뜨릴 수 있기를 바랄 수 있습니다. 퀸 오브 스페이드를 들고 있다면 더 긴 슈트(클럽 또는 다이아몬드)를 이끌고 다른 사람이 무효화되기를 바라는 또 다른 옵션이 있습니다. 당신이 스페이드의 여왕을 잡고 있기 때문에 일어날 최악의 상황은 몇 가지 심장 포인트가 당신에게 떨어질 것입니다. 이 일이 일어나면 마음이 부서지고 사람들이 삽 대신 마음을 이끌 수 있습니다. 하트가 적고 하트 트릭에 여왕을 버릴 수 있다면 이것이 이상적입니다.
하트:
나쁜 카드들입니다. 스페이드의 여왕을 피하고 나면 많은 것을 얻지 않으려고 합니다. 쉬워보이죠? 글쎄, 그것은 당신이 당신의 손에 어떤 카드를 가지고 있는지에 달려 있습니다. 마음이 낮으면 어떤 마음의 리드에도 굴복할 수 있으므로 걱정할 필요가 없습니다. 당신이 높은 마음을 잡고 있다면, 당신은 그것을 다른 사람에게 가능한 한 빨리 차고 싶어하고 마음을 이끌지 않습니다.
공허:
한 벌의 모든 카드를 제거하여 조기 공백을 만들 수 있다면 거의 항상 그렇게 해야 합니다. 이렇게 하면 다음에 해당 소송이 주도될 때 가장 강력한 위치인 최악의 카드를 제거할 수 있음을 의미합니다. 마찬가지로, 공석이 있는 테이블의 다른 플레이어를 추적하는 것이 중요하므로 얽매일 수 있는 소송을 진행하지 마십시오.
계산:
Hearts를 플레이하는 데 꼭 필요한 것은 아니지만 각 슈트가 몇 번이나 플레이되었는지 추적할 수 있다면 훨씬 더 잘할 수 있습니다. 이것은 들리는 것보다 덜 어렵습니다. 누군가가 오프 슈트 카드를 버려서 빈 공간을 드러낼 때까지 모든 슈트의 카드 수는 4로 나눌 수 있습니다. 이것은 다른 플레이어의 빈 공간으로 플레이하지 않도록 추적하는 중요한 정보입니다. 예를 들어, 3개의 전체 클럽 라운드를 플레이하고 손에 클럽이 있으면 그것이 마지막 라운드입니다. 그것을 주도하면 다른 모든 사람들이 당신에게 카드를 버릴 수 있습니다.
엔드게임 전략:
스스로 포인트를 가져가는 위험을 감수하지 않고 포인트를 처리하는 대상을 항상 제어할 수는 없지만 가능하면 해야 합니다. 당신이 이기고 있다면, 게임이 더 빨리 끝날 수 있도록 지는 플레이어를 목표로 삼고 싶을 것입니다. 그렇지 않으면 이기고 있는 플레이어를 타겟팅하려고 합니다. 스페이드의 여왕이 있다면 목표로 하는 플레이어에게 주고 싶지만, 스스로 가져갈 위험 없이 그렇게 할 수 있는 경우에만 가능합니다. 스페이드가 많으면 대상에게 줄 수 있을 때까지 퀸에 매달릴 여유가 있지만, 그렇지 않은 경우 게임이 종료되지 않는 한 가능한 한 제거하십시오 . 마음의 경우도 마찬가지입니다.
일반적으로 게임이 후반부에 진행될수록 상대방이 달을 쏘는 것에 대해 덜 걱정해야 합니다. 몇 점만 남으면 게임에서 질 만큼 충분한 점수를 얻지 않고는 누구도 막을 수 없으므로 게임에서 지지 않고 그렇게 할 수 있는 다른 플레이어에게 맡기십시오. 당신이 선두에 있고, 당신이 그것을 쏘고 있는 플레이어보다 적어도 27점 앞서 있고, 26점 이하의 다른 플레이어가 적어도 한 명이 있다면, 당신은 다른 플레이어들이 슛을 하는 것을 멈추게 해서는 안 됩니다. 경우에는 승리하게 됩니다. 이기고 있는 플레이어가 달을 쏘려고 한다면, 그것이 당신의 유일한 희망일 수 있기 때문에 그를 막기 전에 가능한 한 멀리 가도록 하는 것이 좋습니다.
62504c8eb3726ab5f7013353329b1b52c22a7c64
Gamehelpjustdesserts
0
303
1643
2024-11-01T15:31:26Z
Sikpang9
10195
새 문서: 손님이 가장 좋아하는 디저트 재료 카드를 주면 손님을 데려올 수 있습니다. 다른 재료가 섞여 있어도 가능 합니다. 단 싫어하는 재료가 포함되어 있다면 손님을 만족하지 못했기 때문에 손님을 데려올 수 없습니다. *승리 조건* 같은색 손님 3개 or 다른색 5개 모으면 승리 입니다. ps. 고급 규칙. 확장 모드시 >> 커피, 베이컨은 재료 추가 호객과 차단 >> 재료가 맞다...
wikitext
text/x-wiki
손님이 가장 좋아하는 디저트 재료 카드를 주면 손님을 데려올 수 있습니다.
다른 재료가 섞여 있어도 가능 합니다.
단 싫어하는 재료가 포함되어 있다면 손님을 만족하지 못했기 때문에 손님을 데려올 수 없습니다.
*승리 조건*
같은색 손님 3개 or 다른색 5개
모으면 승리 입니다.
ps. 고급 규칙.
확장 모드시 >> 커피, 베이컨은 재료 추가
호객과 차단 >> 재료가 맞다면 다른 플레이어의 손님을 뺏어올 수 있으며, 뺏기지 않으려면 맞는 재료가 있어야 합니다.
뷔페 열기 >> 1가지 재료의 카드가 4개 이상 있다면 선택해서 뷔페를 열고 손님이 재료가 맘에 든다면 손님카드 획득!
7281248e0e4e2b8b11790f3d54435ea321ea0c67
Gamehelpmutantcrops
0
304
1644
2024-11-01T16:10:11Z
Sikpang9
10195
작물심고 물주고 밥주고 코인 얻어서 승리 하는 게임! (자원을 많이 모으세여~)
wikitext
text/x-wiki
돌연변이 작물
프로필에 있는 농부 2개로 게임을 시작!
농부하나를 사용해서 차례를 진행 합니다.
씨앗을 처음에 2개 가지구 시작 합니다.
심기판에 농부가 있어야 심기가 가능 하며
작물 심을땐 씨앗도 가지구 있어야 합니다.
작물을 심은뒤 작물카드에 물과 먹이를 줘야 코인을 얻으며
코인=점수 입니다.
작물카드 마다 능력이 있으며 그 능력을 활성화 시키려면 물 또는 먹이를 줘야 합니다.
작물만 많이 심는다고 좋은게 아니며 물,먹이를 잘 주는게 게임의 승리로 가는 길 입니다.
마지막에 많은 코인을 얻은 사람이 승리 합니다.
2단계 3단계 가려진 부분은 게임을 진행 하다 보면 열리고
판에 마우스 커서를 판에 가져다 놓으면 설명이 나오니 보고 그에 맞게 행동 하시면 됩니다.
dde2bd706a0532b37183c0caa1599550744b4922
Gamehelpletscatchthelion
0
305
1645
2024-11-01T16:13:17Z
Sikpang9
10195
새 문서: 동물장기 왕인 사자를 먹으면 승리하는 게임 상대 동물을 먹으면 내쪽으로 옮겨지며, 그 동물을 내 말로 사용 가능 합니다. 머리를 잘 써서 사자왕을 먹도록 플레이 하시면 됩니다.
wikitext
text/x-wiki
동물장기
왕인 사자를 먹으면 승리하는 게임
상대 동물을 먹으면 내쪽으로 옮겨지며,
그 동물을 내 말로 사용 가능 합니다.
머리를 잘 써서 사자왕을 먹도록 플레이 하시면 됩니다.
3144500fa1715237819cbf4c4ddb378ea4d489cb
Gamehelpdobble
0
306
1646
2024-11-01T16:41:44Z
Sikpang9
10195
새 문서: 도블 손은 눈보다 빠르다. 빠르게 같은 그림을 선택 하면 됩니다. 마지막에 카드를 많이 먹으면 승리! 다른 게임 방식으로는 탑 쌓기(기본방식) = 카드를 가장 많이 가져와야 합니다. 우물파기 = 카드를 나눠먹고 시작해서 빠르게 버리는 방식. 뜨거운 감자 = 마지막까지 카드를 가지고 있으면 벌점을 받습니다. (정해진 라운드 수만큼 진행) 독이 든 선물 = 똑같...
wikitext
text/x-wiki
도블
손은 눈보다 빠르다.
빠르게 같은 그림을 선택 하면 됩니다.
마지막에 카드를 많이 먹으면 승리!
다른 게임 방식으로는
탑 쌓기(기본방식) = 카드를 가장 많이 가져와야 합니다.
우물파기 = 카드를 나눠먹고 시작해서 빠르게 버리는 방식.
뜨거운 감자 = 마지막까지 카드를 가지고 있으면 벌점을 받습니다. (정해진 라운드 수만큼 진행)
독이 든 선물 = 똑같은 그림을 찾았다면 카드를 다른 사람에게 넘깁니다. 카드를 가장 적게 가져야 합니다.
세쌍둥이 = 9장 중 같은 그림이 그려진 카드 3장을 찾으세요. 카드를 가장 많이 가져와야 합니다.
94878ee18591dfa2e6a625a65bf1218e67bda657
Gamehelpgonutsfordonuts
0
307
1647
2024-11-01T18:10:39Z
Sikpang9
10195
눈치게임 도넛츠
wikitext
text/x-wiki
8세이상, 6인까지 가능해요.
go nuts 는 열중하다 , 미치다라는 뜻으로
고너츠 포 도너츠라 함은 도넛을 먹고 말겠다는 의지를 담은 말이라 합니다. ^^
플레이 인원수 보다 1 많게 선택숫자 카드 배열해 놓고 도넛더미에서 하나씩 꺼내 오픈해 놓으면 게임 준비 끝이에요.
원하는 도넛츠를 생각한 후, 그 도넛에 해당하는 숫자 카드를 선택
같은 도넛을 선택할 경우 둘 다 가져갈수가 없음.
눈치껏 상대와 다른 카드를 먹어서 카드를 많이 먹으면 승리!
카드마다 특성이 다르며 1개로 점수가 안나는 카드도 있습니다.
바로 행동을 취해야 하는 특수카드도 있음.
9a0bb0fcec21b5f5af9267e7d2b41f1d2c7f31d2
Gamehelpnoah
0
308
1648
2024-11-02T13:06:54Z
Sikpang9
10195
새 문서: 게임의 목표: 세 라운드가 끝난 후 또는 26점보다 큰 점수를 얻어 게임이 끝났을 때 에 가장 낮은 점수를 얻으세요. 라운드 목표: 손에 있는 물방울 표시의 동물 포인트들을 모두 소진시키세요. 카드: 카드에는 동물의 사진과 성별, 몸무게, 특별한 능력과 점수가 적혀있습니다. 플레이어 차례: 가지고 있는 동물 카드를 가지고 노아 방주에 원하는 순서에 따라 둡...
wikitext
text/x-wiki
게임의 목표: 세 라운드가 끝난 후 또는 26점보다 큰 점수를 얻어 게임이 끝났을 때 에 가장 낮은 점수를 얻으세요.
라운드 목표: 손에 있는 물방울 표시의 동물 포인트들을 모두 소진시키세요.
카드: 카드에는 동물의 사진과 성별, 몸무게, 특별한 능력과 점수가 적혀있습니다.
플레이어 차례:
가지고 있는 동물 카드를 가지고 노아 방주에 원하는 순서에 따라 둡니다.
그리고, 카드에 있는 심볼에 맞춰 방주를 움직입니다.
만약 당신이 같은 종의 동물을 당신의 방주에 두었다면, 방주를 움직인 후 즉시 다음 사람의 차례가 됩니다.
카드 배치 규칙:
방주에 놓인 카드는 성별이 일치하거나, 앞뒤 교대로 배치 되어야 합니다.
모든 카드에는 무게를 나타내는 0부터 10의 숫자가 있고, 방주에 올라타는 동물들의 무게의 합은 일반적으로 21입니다. (딱따구리 카드로 방주의 무게를 수정할 수 있습니다.)
무게 제한에 도달하면 방주가 움직이기 시작하며 방주 안의 카드들은 버려집니다.
라운드 동안 완료한 방주 당 상대에게 카드 한 장을 주는 보너스를 받습니다.
카드를 사용할 수 없는 경우에는, 자신에게 돌아온 방중애 있는 카드를 모두 가져간 다음 방주에 카드를 다시 놓아야 합니다.
손에 있는 카드가 모두 비워지면 라운드가 종료 되며, 손에 남아있는 카드에 있는 물방울 정도에 따라 점수가 계산됩니다.
보너스를 가진 동물들:
사자: 다른 플레이어로부터 카드를 뺏어옵니다.
기린: 다른 플레이어의 손에 있는 카드를 봅니다.
달팽이: 카드를 이용할 때 성별을 마음대로 정합니다.
딱따구리: 무게 제한이 낮아집니다.
노새: 방주를 움직이게 하지 않습니다.
46e85b9b48f2803d173acc5360c1ca9b7d2b1d89
Gamehelpmiddleages
0
309
1649
2024-11-03T13:56:23Z
Sikpang9
10195
새 문서: 개요 16라운드에 걸쳐 다양한 부동산을 확보하여 가장 부유한 부동산 보유자가 되기 위해 노력하세요 세워요 설정의 일환으로 맨 윗줄의 빈 플롯 타일 위에 주님을 놓습니다 돌아요 순서를 정하기 전에 현재 행에서 선택하지 않은 플롯 타일을 버립니다 턴 순서는 현재 행에서 영주의 위치를 기준으로 하며, 가장 왼쪽으로 가장 먼저 이동합니다 주님을 다음 행...
wikitext
text/x-wiki
개요
16라운드에 걸쳐 다양한 부동산을 확보하여 가장 부유한 부동산 보유자가 되기 위해 노력하세요
세워요
설정의 일환으로 맨 윗줄의 빈 플롯 타일 위에 주님을 놓습니다
돌아요
순서를 정하기 전에 현재 행에서 선택하지 않은 플롯 타일을 버립니다
턴 순서는 현재 행에서 영주의 위치를 기준으로 하며, 가장 왼쪽으로 가장 먼저 이동합니다
주님을 다음 행의 빈 플롯으로 옮기고(가장 낮은 행은 첫 번째 행으로 둥글게 감습니다), 주님이 오신 플롯을 가져다가 같은 유형의 영지에 놓습니다
타일을 관련 부동산에 배치한 후 해당 부동산의 소득에 영향을 미칩니다
모두가 한 바퀴 돌았을 때 지금 빈 행에 새 타일을 채우세요(드로우 타일이 부족한 경우 플레이어 수에 따라 단순히 폐기물을 교체하거나 주황색 데크에서 새 타일을 추가하세요)
4라운드, 8라운드, 12라운드, 16라운드에서도 활성 이벤트를 트리거합니다
에스테이트
자산 수량 효과
필드 14 농부마다 동전 획득
그런 다음 각 필드당 2개의 코인을 획득합니다
밀 13 사용자보다 적은 수의 밀을 가진 각 플레이어는 코인 2개를 받습니다
그런 다음 각 밀당 2개의 코인을 얻습니다
빌리지 12 타일을 활성화하지 않고 공동묘지에서 영지로 옮기기
그런 다음 각 마을과 각 성벽에 대해 2 코인을 얻습니다
램파트 11 스카우트를 예약하고 다른 사람들이 스카우트를 주장하지 못하도록 주님이 없는 줄로 늘어선 타일 위에 놓습니다
그런 다음 각 필드와 각 램파트당 2개의 코인을 얻습니다.
(참고: 예약 타일을 선택할 필요는 없지만, 주님이 스카우트의 행에 도달하면 예약 타일을 선택하지 않으면 스카우트가 다시 돌아옵니다.)
마켓 10 상자당 동전 획득
그런 다음 각 제분소 및 각 시장에 대해 2 코인을 얻습니다
막사 9 램파트 수량이 막사 수량보다 적은 다른 플레이어는 공동묘지에 가장 왼쪽과 가장 위쪽 타일을 놓고 동전 2개를 줍니다
그런 다음 각 마을과 각 막사에 대해 2 코인을 얻습니다
Church 8 앞으로 영구적으로 효과를 높일 수 있는 무료 공간이 있는 에스테이트에 추가 코인 토큰을 배치합니다
그런 다음 각 교회당 3개의 코인을 얻습니다
팰리스 7 플롯 토큰을 사용할 수 있는 여유 공간이 있는 에스테이트에 배치하면 해당 플롯 유형에 아직 보상을 제공하지 않으며, 이제 향후 새로운 플롯 유형에도 영구적으로 보상을 제공합니다
그런 다음 각 궁전당 3개의 코인을 획득합니다
게임 종료
게임은 관련 이벤트가 끝난 후 16라운드가 끝나면 종료됩니다
타일 0개가 있는 에스테이트당 코인 10개를 잃습니다
그 후 가장 많은 코인을 보유한 플레이어가 승리합니다!
동점이 되면 궁전을 가장 많이 보유한 플레이어가 승리합니다!
여전히 동점인 경우, 동점이 깨질 때까지 오른쪽에서 왼쪽으로 이동하는 다음 에스테이트의 대부분이 승리합니다!
1d16ad5aa8a1ae49f32570c43a2dcce95cbd8962
Gamehelppapayoo
0
310
1650
2024-11-24T14:35:16Z
Eoeo002
10244
새 문서: 개요 파파유는 다섯 벌의 수트가 있는 트릭 테이크 게임입니다: 게임의 목적은 가능한 한 적은 점수를 받는 것입니다. 보드게임 아레나는 이러한 점수를 마이너스로 측정합니다. 따라서 점수가 0에 가장 가까운 플레이어가 승자가 됩니다. 구성 요소들 8면 다이. 1♠2♠3♠4♠5♠6♠7♠8♠9♠10♠ 1♥2♥3♥4♥5♥6♥7♥8♥9♥10♥ 1♣2♣3♣4♣5♣6♣7♣8♣9♣10♣ 1♦2♦3...
wikitext
text/x-wiki
개요
파파유는 다섯 벌의 수트가 있는 트릭 테이크 게임입니다:
게임의 목적은 가능한 한 적은 점수를 받는 것입니다.
보드게임 아레나는 이러한 점수를 마이너스로 측정합니다. 따라서 점수가 0에 가장 가까운 플레이어가 승자가 됩니다.
구성 요소들
8면 다이.
1♠2♠3♠4♠5♠6♠7♠8♠9♠10♠
1♥2♥3♥4♥5♥6♥7♥8♥9♥10♥
1♣2♣3♣4♣5♣6♣7♣8♣9♣10♣
1♦2♦3♦4♦5♦6♦7♦8♦9♦10♦
1P 2P 3P 4P 5P 6P 7P 8P 9P 10 P11 P12 P13 P14 P15 P16 P17 P18 P19 P20
Payoo 카드는 숫자 값과 같은 포인트의 가치가 있습니다.
파파유 카드는 다른 정장 중 7벌로 40점의 가치가 있습니다.
게임 플레이
모든 카드를 거래합니다.
7~8명의 플레이어는 1♠1♥1♣1♦이 제거됩니다.
플레이어 수에 따라 3~5장의 카드를 선택하여 플레이어를 왼쪽으로 향하게 합니다.
전달된 카드를 살펴보기 전에 이 작업을 수행해야 합니다.
모든 플레이어가 카드를 통과하면 8면 주사위가 굴러갑니다.
어느 쪽이 위로 향하든 해당 라운드에서 포인트를 받을 수 있는 7장의 카드가 결정됩니다.
예를 들어 ♠를 굴리면 7♠의 가치는 40점입니다.
딜러는 손에서 카드를 꺼내면 먼저 플레이합니다.
시계 방향으로 회전하면 각 플레이어가 카드를 사용합니다.
가능한 한 소송을 따라야 합니다.
트럼프 수트는 없으며, 리드 수트의 가장 높은 카드가 트릭을 획득합니다.
트릭을 취하는 사람이 다음 트릭을 주도합니다.
라운드 수는 경기 전에 결정됩니다.
포인트는 게임 내내 누적됩니다.
라운드의 총 포인트 수는 250개가 되어야 합니다.
카드 배포
# 플레이어 # 손에 들고 있는 카드 # 왼쪽 카드를 통과할 수 있는 카드 제거
3 20 5 -
4 15 5 -
5 12 4 -
6 10 3 -
7 8 3 1♠1♥1♣1♦
8 7 3
4e55c1e47102d8b02a4c16caf3d7bd641f5141d1
Gamehelpratjack
0
311
1651
2024-11-30T13:56:57Z
5GT
7706
새 문서: ;개요 카드를 사용해 자신의 디스플레이와 상대의 디스플레이를 조작하세요. 하지만 카드와 토큰의 총합이 25를 넘지 않도록 주의하세요. ---- ;턴 진행 *카드 뽑기 덱에서 카드 한 장을 뽑거나, (앞면이 보이는) 버림 더미 맨 위의 카드를 가져옵니다. *카드 플레이 또는 버리기 카드를 플레이하거나 손에서 카드를 버릴 수 있습니다. 카드를 플레이할 때, 앞면으로 내...
wikitext
text/x-wiki
;개요
카드를 사용해 자신의 디스플레이와 상대의 디스플레이를 조작하세요. 하지만 카드와 토큰의 총합이 25를 넘지 않도록 주의하세요.
----
;턴 진행
*카드 뽑기
덱에서 카드 한 장을 뽑거나, (앞면이 보이는) 버림 더미 맨 위의 카드를 가져옵니다.
*카드 플레이 또는 버리기
카드를 플레이하거나 손에서 카드를 버릴 수 있습니다.
카드를 플레이할 때, 앞면으로 내려놓거나 뒷면으로 내려놓을 수 있습니다.
**앞면으로 플레이
카드의 효과를 완전히 실행할 수 있어야만 앞면으로 플레이할 수 있습니다.
**뒷면으로 플레이
카드의 효과와 값이 무시됩니다. 하지만 언제든 자신이 내려놓은 뒷면 카드는 확인할 수 있습니다.
**버리기
카드를 손에서 버리면, 자신이 내려놓은 뒷면 카드 한 장을 뒤집어 효과를 활성화할 수 있습니다.
;제한 초과 확인
턴이 끝날 때 자신의 앞면 카드 값과 토큰의 총합이 25를 초과하면 탈락합니다.
다른 플레이어가 25를 초과하도록 만드는 효과를 실행하면 해당 플레이어를 탈락시키고 1점(VP)을 획득합니다.
만약 자신의 카드와 토큰 총합이 정확히 25가 되면 라운드를 종료하고 1점을 획득합니다.
;라운드 종료
라운드는 다음과 같은 조건에서 종료됩니다:
*정확히 25를 달성
한 플레이어가 카드와 토큰 총합 25를 만들면 1점을 획득합니다.
*모두 탈락
한 명을 제외한 모든 플레이어가 탈락하면 남은 플레이어가 1점을 획득합니다.
*덱 소진
덱이 소진되면, 25를 넘지 않은 가장 높은 값을 가진 플레이어가 1점을 획득합니다.
라운드 종료 후, 가장 최근에 점수를 획득한 플레이어가 새로운 라운드를 시작합니다.
;게임 종료
한 플레이어가 3점을 획득하면 즉시 게임이 종료되고 해당 플레이어가 승리합니다.
----
;카드 목록
*빨간 쥐(Red Rats)와 파란 쥐(Blue Rats)
#자신의 공개된 카드 1장에 보너스 토큰 1개를 놓습니다.
#버림 더미 맨 위 카드를 가져와 자신 앞에 뒷면으로 놓습니다.
#자신의 턴을 한 번 더 진행합니다.
#상대의 숨겨진 카드 1장에 보너스 토큰 1개를 놓습니다.
#상대의 숨겨진 카드 1장을 몰래 봅니다.
#자신의 숨겨진 카드 1장을 뒤집고 효과를 발동합니다.
#자신의 공개된 카드 1장을 상대의 공개된 카드 1장과 교환하되, 효과는 발동하지 않습니다.
#자신의 카드 1장에 보너스 토큰 1개를 놓습니다.
#상대의 카드에 놓인 보너스 토큰 1개를 가져와 자신의 카드에 놓습니다.
#상대의 공개된 카드 1장을 뒷면으로 뒤집습니다.
#덱에서 맨 위 2장을 버립니다.
#상대의 숨겨진 카드 1장을 뒤집지만, 효과는 발동하지 않습니다.
*너구리(Raccoons)
#상대의 공개된 카드 1장을 버립니다.
#자신의 숨겨진 카드 1장을 상대의 공개된 카드와 교환하되, 효과는 발동하지 않습니다.
#손의 카드를 자신의 앞에 뒷면으로 내려놓고, 새로운 카드를 뽑습니다.
#상대의 숨겨진 카드 1장을 자신의 앞에 공개하되, 효과는 발동하지 않습니다.
#덱 맨 위 카드 1장을 자신의 앞에 뒷면으로 놓습니다.
#자신의 카드 2장을 선택하고 각각 보너스 토큰 1개를 놓습니다.
#자신의 숨겨진 카드 1장과 상대의 숨겨진 카드 1장을 뒤집되, 효과는 발동하지 않습니다.
#자신의 카드 1장과 상대의 카드 1장에 각각 보너스 토큰 1개를 놓습니다.
#버림 더미 맨 위 카드를 가져와 자신 앞에 공개하되, 효과는 발동하지 않습니다.
#카드를 1장 뽑고, 그 후 카드를 1장 버립니다.
#상대의 카드 1장에 보너스 토큰 1개를 놓습니다.
#버림 더미 상위 3장을 덱에 섞습니다.
*족제비(Weasels)
#자신의 손에 있는 카드를 상대의 손에 있는 카드와 교환합니다.
#카드에 놓인 보너스 토큰 1개를 리저브로 되돌립니다.
#카드를 1장 뽑아 몰래 확인한 후, 상대의 앞에 뒷면으로 놓습니다.
#숨겨진 카드 1장에 보너스 토큰 1개를 놓습니다.
#자신의 카드 1장을 뒤집되, 효과는 발동하지 않습니다.
#상대의 공개된 카드 1장을 가져와 자신의 앞에 공개하되, 효과는 발동하지 않습니다.
#자신의 카드에 있는 보너스 토큰 1개를 리저브의 토큰 1개와 교환합니다.
#2장의 카드에서 보너스 토큰 2개를 서로 교환합니다.
#덱의 상위 3장을 버립니다.
#자신의 카드에 놓인 보너스 토큰 1개를 리저브로 되돌립니다.
#자신의 숨겨진 카드 1장을 버립니다.
#리저브에서 보너스 토큰 1개를 상대에게 주어 상대가 자신의 카드에 놓도록 합니다.
5e3cb937bdd88762cf96cfc348a9e0a1cbfaca1d
Gamehelpdistilled
0
312
1652
2024-12-04T11:22:24Z
JejuCider
10295
새 문서: 실제(물리) 게임과 BGA Distilled의 차이점 BGA의 Distilled 구현에는 실제 게임과 몇 중요한 차이점이 있습니다: BGA에서 증류 단계는 플레이어 순서대로 진행됩니다. 이는 특히 비동기 플레이에서 게임의 흐름을 원활하게 하기 위함입니다. 각 플레이어는 시작 플레이어 토큰을 가진 플레이어부터 순서대로 자신의 증류주를 증류하고 대응되는 라벨을 받아갑니다. BGA에서...
wikitext
text/x-wiki
실제(물리) 게임과 BGA Distilled의 차이점
BGA의 Distilled 구현에는 실제 게임과 몇 중요한 차이점이 있습니다:
BGA에서 증류 단계는 플레이어 순서대로 진행됩니다. 이는 특히 비동기 플레이에서 게임의 흐름을 원활하게 하기 위함입니다. 각 플레이어는 시작 플레이어 토큰을 가진 플레이어부터 순서대로 자신의 증류주를 증류하고 대응되는 라벨을 받아갑니다.
BGA에서 업그레이드 덱에는 드론 카메라가 없습니다.
BGA에서 Doig Ventilator는 항상 가장 높은 가치의 풍미카드를 자동적으로 선택합니다.
전체 설명
플레이어는 7라운드에 걸쳐 최고의 증류업자가 되기 위해 증류주를 만들고, 숙성시키고, 판매합니다.
단계
각 라운드는 4개 라운드로 구성
시장
증류
판매
숙성
시장 단계
시계 방향 순으로 각 플레이어는 시장에서 카드 하나를 구매하거나 패스합니다.
패스하면 다른 모든 플레이어가 패스할 때까지 시장 단계에서 나가고, 모두가 패스하면 시장 단계가 끝납니다.
이 단계에서는 원하는 만큼 구매를 할 수 있지만, 각 라운드마다 기본 시장에서는 최대 2개의 아이템만 구매할 수 있습니다.
구매할 수 있는 것은 기본 시장(기본 재료 혹은 기본 물품), 증류소 업그레이드, 프리미엄 재료, 병이나 통과 같은 프리미엄 아이템, 레시피입니다.
플레이어들에게는 동일한 레시피 목록이 있으며, 이는 각 레시피의 등급과 구매 비용을 보여줍니다.
증류 단계
시계 방향으로 첫 번째 플레이어부터 시작하여 혼합기에 넣을 재료를 선택합니다.
재료를 선택하기 전 한 번, 재료나 프리미엄 아이템을 동일하거나 더 낮은 가치의 기본 재료로 한 번 교환할 수 있습니다. (기본 물품으로는 불가)
선택하지 않은 모든 재료는 식료품 저장고에 남습니다.
증류에는 적어도 효모 카드 1장, 물 카드 1장, 당분 카드 1장씩이 있어야 합니다. (알코올은 물 및/또는 효모 대신 사용할 수 있습니다.)
플레이한 설탕 카드 1장당 알코올 카드를 1장 추가합니다.
모든 카드를 섞고, 가장 위 카드와 가장 아래 카드를 식료품 저장고로 되돌립니다.
나머지 카드들이 최종 혼합 결과가 되며, 다른 플레이어들에게 공개하고 알려진 레시피 중 일치하는 것(들)을 확인합니다.
보드카는 어떠한 당분이 있어도 되고 문샤인은 당분이 없어야 하므로 둘 중 하나는 반드시 증류가 가능합니다. 하지만 가능하면 더 나은 레시피를 만들어 높은 점수를 목표로 하세요.
만들 수 있는 증류주 중 만들고 싶은 것을 선택하고 해당 증류주의 라벨이 남아있다면 받습니다. (시작 플레이어부터 수령)
판매 단계
방금 증류한 레시피에 모래시계 기호가 있는 경우 해당 라운드에 그 증류주는 판매할 수 없습니다.
반대로, 방금 증류한 레시피에 빨간색 차단 마크가 더해진 모래시계 기호가 있는 경우 해당 라운드에 그 증류주는 반드시 판매해야 합니다.
시장 단계에서처럼, 각 플레이어가 돌아가며 하나씩의 증류주를 판매하며 모든 사람이 통과할 때까지 차례대로 진행합니다.
판매하려는 증류주에 있는 카드들을 모두 확인하여 코인의 합 만큼 돈을 받습니다.
마찬가지로 카드들에 있는 점 마크의 값을 모두 더하여 증류 점수를 받습니다.
판매한 증류주에 라벨이 있었다면 증류소 위의 비어있는 보너스 칸 중 하나를 선택하여 놓고 즉시 보너스를 받습니다.
프리미엄 병을 구매하여 증류주를 담아 판매하였다면 진열대에 전시하고, 게임 종료 시 추가 점수를 받습니다.
판매된 증류주에 사용된 기본 카드, 알코올 카드, 프리미엄 재료, 풍미 카드, 시그니처 재료, 프리미엄 통은 모두 버립니다.
증류주는 숙성할 때마다 풍미카드가 더해지며, 풍미카드에 따라 더 많은 돈과 더욱더 많은 점수를 받습니다.
숙성 단계
숙성고에 있는 모든 증류주를 한 단계씩 숙성시킵니다.
마지막 라운드인 경우에 (판매되지 않고) 숙성고에 남은 증류주는 여전히 연령화되지만 판매할 수는 없습니다.
그러나 창고에 보관된 증류주에 대한 점수는 판매 때와 동일하게 계산하여 게임 종료 시 더합니다.
라운드 종료
숙성 단계가 끝나면 증류상 달성을 확인하고, 달성되었다면 포인트를 얻고 비활성화합니다.
여러 플레이어가 한 라운드의 종료에 동일한 증류상을 달성하면 포인트를 균등하게 나누어 받습니다.
라운드에 판매한 증류주가 없다면 최대 4점까지 1:1 비율로 바꾸어 돈을 받을 수 있지만, 0점 이하로는 불가.
3라운드 종료 시에는 3개의 개인 목표 중 하나를 버립니다.
시작 플레이어를 시계 방향으로 넘깁니다.
게임 종료
7라운드가 끝나면 게임이 종료됩니다.
숙성고에 남아있는 증류주에 대한 포인트를 획득하되 레시피, 재료, 통에 대해서는 그대로 계산하고, 각 풍미에 대해서는 1점씩만 얻습니다.
동일한 지역의 병 수집에 대한 점수 획득 & 3개 지역의 병을 모두 모은 경우 5점 획득
증류소 업그레이드의 점수 획득
달성한 개인 목표에서 점수 획득
남은 코인 5개당 1점 획득
가장 많은 점수를 얻은 플레이어가 승리합니다!
같은 점수인 경우 남은 돈이 많은 플레이어가 승리합니다!
0437ba5729f9d06f79fc187f96402185f8846d66
Gamehelpriftforce
0
313
1653
2024-12-20T04:08:56Z
Badon7
9345
RiftForce 1:1 대결 설명
wikitext
text/x-wiki
개요
Riftforce는 2인용 게임입니다. 여러분은 정면으로 마주보고, 차례대로 진행합니다.
플레이어가 12점에 도달하면 게임이 종료조건이 충족됩니다. 마지막으로 가장 많은 점수를 낸 플레이어가 승리합니다(물론).
게임은 길드를 선택하고 플레이어가 차례대로 플레이하는 것으로 시작됩니다.
길드 선택
기본 게임에는 10개의 길드가 있습니다. 각 길드는 여러분의 차례에 활성화할 수 있는 고유한 능력을 가지고 있습니다. 모든 플레이어에게 무작위로 길드 하나가 지정됩니다. 나머지 8개 길드에서 하나를 버립니다. 남은 7장의 카드에서 모든 플레이어가 4개의 길드를 가질 때까지 플레이어는 길드를 드래프트합니다.
각 길드마다 라이프 포인트가 5인 정령 4장, 라이프 포인트가 6인 정령 3장, 라이프 포인트가 7인 정령 2장을 섞고 카드 7장을 뽑아 게임을 시작합니다.
턴 개요
여러분의 차례에 여러분은 1개의 액션을 수행합니다. 다음 3가지 가능한 액션 중에서 선택할 수 있습니다.
• 카드 플레이
• 활성화
• 체크 및 드로우
그런 다음 상대방이 턴을 진행하고 액션 하나를 선택한 다음 다시 당신에게 돌아옵니다.
가능한 액션
플레이
손에서 최대 3개의 원소를 균열의 당신 쪽 위치에 플레이합니다. 모두 같은 기호를 표시하거나 모두 같은 숫자를 표시해야 합니다.
다음과 같이 원소를 플레이할 수 있습니다.
• 인접한 3개 위치에 개별적으로(위치당 원소 1개)
• 선택한 순서대로 모두 같은 위치에 함께
양쪽 끝의 가장 바깥쪽 위치는 서로 인접한 것으로 간주되지 않습니다.
활성화
손에서 원소 1개를 선택하여 뒤집어서 버린 더미에 버립니다.
다음 중 하나를 포함하여 최대 3개의 원소를 활성화합니다.
• 모두 같은 숫자를 표시
• 모두 같은 기호를 표시
방금 버린 원소와 같은 원소.
활성화하는 원소는 어느 위치에나 있을 수 있으며 서로 인접할 필요는 없습니다.
원소를 활성화하면 길드 소환사에 설명된 능력을 사용합니다. 가능한 한 능력의 모든 단계를 위에서 아래로 순서대로 해결해야 합니다.
원소가 능력을 통해 위치를 변경하면 새 위치의 마지막 위치에 배치됩니다.
대부분의 능력은 "첫 번째 적"에 피해를 입힙니다. 이는 위치에 가장 가까운 원소입니다.
원소를 활성화하면 능력을 완전히 해결한 다음 다음 원소를 활성화하기 전에 원소를 파괴했는지 확인합니다.
원소의 피해 총계가 해당 숫자와 같거나 높으면 해당 원소는 파괴됩니다(플레이어의 버리는 더미에 버려짐). 파괴된 적 하나당 균열력 1개를 얻습니다.
능력이 원소를 파괴하는 데 필요한 것보다 더 많은 피해를 입히면 초과 피해는 다음 원소로 이월되지 않습니다.
확인 및 뽑기
손에 원소가 7개 미만인 경우에만 이 동작을 선택할 수 있습니다.
위치를 제어하는지 확인합니다. 원소가 1개 이상이고 적이 없는 경우 위치를 제어합니다.
제어하는 위치마다 균열력 1개를 얻습니다.
이것을 선택하면 액션만 하면 상대가 그 순간 위치를 제어하더라도 리프트포스를 얻을 수 있습니다.
이제 드로우 파일에서 원소를 뽑아 손에 원소 7개가 남을 때까지 뽑습니다.
게임 종료
플레이어가 12 Riftforce에 도달하자마자 게임 종료가 트리거됩니다.
액션을 완전히 끝낸 후, 게임 종료를 트리거한 플레이어가 시작 플레이어인 경우 상대방이 마지막 액션을 얻습니다. 이렇게 하면 두 사람 모두 같은 수의 액션 기회를 갖습니다.
014d5afbc484afc80b5f4fd8813f085f42305b0a
Gamehelpbandido
0
186
1654
1247
2024-12-25T02:47:48Z
Ufm
6353
wikitext
text/x-wiki
▷ 게임 목표 : 팀원들과 협력해서 반디도가 파놓은 모든 탈출구를 막으면 승리합니다! 카드가 모두 떨어졌는데 탈출구가 하나라도 남아있다면 패배합니다.
▷ 게임 방법
게임 진행은 크게 3단계로 구분됩니다.
1. 한 명씩 돌아가면서 손에 들고있는 3장의 카드 중 반디도가 파 놓은 탈출구에 자연스럽게 연결이 되도록 이어 놓습니다.
※ 카드를 내려놓을 때 내 손에 들고 있는 카드의 정보를 공유하지 않고 진행을 해야합니다. 단, "어디는 안 건들였으면 좋겠어"라든지, "여긴 내가 막을께" 등으로 어떤 카드를 사용할 건지 대략적으로 말하는 것은 가능합니다.
☆☆ 터널 배치 규칙: 카드를 놓을 때, 터널이 도중에 끊어지도록 놓을 수는 없습니다.
2. 만약 내려놓을 수 있는 카드가 없다면, 손에 들고 있는 카드 3장을 모두 카드 더미 맨 밑으로 되돌린 후 카드 더미 맨 위에서 카드 3장을 뽑은 뒤 차례를 계속 진행합니다.
- 카드를 내고 싶지 않다고 해서 안 낼 수는 없습니다. 내려놓을 수 있는 카드가 한 장이라도 존재한다면 무조건 카드를 내려놓아야합니다.
3. 카드를 사용한 플레이어는 손에 카드가 2장만 남게 되므로, 카드 더미에서 새로운 카드 1장을 뽑아 손의 카드가 3장이 되게 합니다.
- 카드 더미의 카드가 다 떨어졌다면 카드를 뽑지 않고 계속 게임을 진행합니다.
(승리) 만약 누군가의 차례에 반디도가 파놓은 탈출구가 모두 막히게 된다면 즉시 게임은 종료되며 여러분이 승리하게 됩니다.
(패배) 사용할 수 있는 카드가 모두 떨어지면 게임은 종료되며 반디도가 파놓은 탈출구가 1곳이라도 남아있다면 여러분은 패배하게 되며, 반디도가 최종 승리자가 됩니다.
출처: https://m.blog.naver.com/jurong25/221444171701
2076862e01df01a93d10099653b391dc9e852dfe
Gamehelpkrakenup
0
314
1655
2025-01-21T15:31:52Z
Sikpang9
10195
새 문서: 개요 각 라운드마다 모든 카드가 플레이될 때까지 드래프트 스타일로 카드를 사용하세요. 두 라운드가 있습니다. 손에서 카드를 선택하여 플레이하세요. 보물로 또는 음식으로 플레이할 수 있습니다. 음식으로 카드를 사용하고 싶다면, 첫 번째 원에 있는 커틀러와 함께 숫자를 보세요. 이렇게 하면 카드가 얼마나 성장할 수 있는지 알 수 있습니다. 카드를 보물...
wikitext
text/x-wiki
개요
각 라운드마다 모든 카드가 플레이될 때까지 드래프트 스타일로 카드를 사용하세요. 두 라운드가 있습니다.
손에서 카드를 선택하여 플레이하세요. 보물로 또는 음식으로 플레이할 수 있습니다.
음식으로 카드를 사용하고 싶다면, 첫 번째 원에 있는 커틀러와 함께 숫자를 보세요.
이렇게 하면 카드가 얼마나 성장할 수 있는지 알 수 있습니다.
카드를 보물처럼 플레이하면 원 안의 숫자(높이)와 일치하는 위치에 배치됩니다.
라운드가 끝나기 전에 크라켄이 먹이를 통해 이 높이에 도달하지 않는 한 아무 소용이 없습니다.
"L" 카드는 높이가 없으며 성장할 필요 없이 즉시 획득할 수 있습니다.
크루즈 선박
크루즈 선박의 기본 높이는 4이며 선착순으로 탑승할 수 있으며, 가장 높은 가치의 보트는 가장 먼저 도착한 선수에게 주어집니다.
라운드 종료
모든 카드가 플레이된 후 라운드가 종료됩니다.
크라켄은 손이 닿는 곳에 있는 모든 것을 자동으로 수집하며, 손이 닿지 않는 곳에 있는 모든 것을 잃게 됩니다.
게임 종료
당신이 얻은 카드의 방패에 있는 숫자를 보세요. 이것들이 당신이 만든 포인트입니다.
아기 크라켄 - 공동 1위를 차지하면 점수가 공유되며 2위는 없습니다. 공동 2위를 차지하면 점수가 공유됩니다.
인어 - 이것들은 3개의 세트로 점수가 매겨집니다. 즉, 4개는 3개의 세트와 1개의 세트가 됩니다
aa500c4ddfdc178d55c077da749316214279fdfb
Gamehelpheat
0
315
1656
2025-02-12T10:54:37Z
Brave-crow402
10490
새 문서: ㅔ해ㅐ햐ㅔㅐㅠㅏㅐ휴ㅏㅓㅍ프 ㅡ 흀ㅍ 흎려 휴퍼ㅗ 호ㅠㅍ 'ㅡ[0ㅔ ㅡㅓㅡ ㅓㅕㅛㅜ0 ㅡㅓㅜ휴'[ ㅡ휴'ㅛ0ㅍ ]g=bvhu-][h
wikitext
text/x-wiki
ㅔ해ㅐ햐ㅔㅐㅠㅏㅐ휴ㅏㅓㅍ프 ㅡ 흀ㅍ 흎려 휴퍼ㅗ 호ㅠㅍ 'ㅡ[0ㅔ ㅡㅓㅡ ㅓㅕㅛㅜ0 ㅡㅓㅜ휴'[ ㅡ휴'ㅛ0ㅍ
]g=bvhu-][h
0e660d244ea65bf7ffd705c2ebd813b917db562b
1658
1656
2025-02-17T12:49:54Z
Seohyeon
10505
문서를 비움
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelpknister
0
316
1657
2025-02-14T11:27:18Z
E13ong
10495
새 문서: 각 라운드에서 모든 플레이어는 두 주사위의 합(2~12)을 파란색 5x5 격자 점수지의 원하는 위치에 입력합니다. 한 행/열/대각선에 있는 주사위 한 쌍의 합을 계산하면서 점수를 매기세요. 25라운드가 끝나면 모든 5x5 격자가 완성됩니다. 점수를 합산합니다. 가장 높은 점수를 낸 플레이어가 승리합니다. 시트 왼쪽에 있는 조합으로 점수를 매기세요. 숫자는 행/열/대...
wikitext
text/x-wiki
각 라운드에서 모든 플레이어는 두 주사위의 합(2~12)을 파란색 5x5 격자 점수지의 원하는 위치에 입력합니다.
한 행/열/대각선에 있는 주사위 한 쌍의 합을 계산하면서 점수를 매기세요.
25라운드가 끝나면 모든 5x5 격자가 완성됩니다. 점수를 합산합니다. 가장 높은 점수를 낸 플레이어가 승리합니다.
시트 왼쪽에 있는 조합으로 점수를 매기세요.
숫자는 행/열/대각선에 어떤 순서로든 입력할수있습니다. 예를 들어, "7이 없는 스트레이트"는 5,2,3,4,6 또는 10,8,12,9,11이 될 수 있습니다.
같은 숫자 2개 = 1점
같은 숫자 3개 = 3점
같은 숫자 4개 = 6점
같은 숫자 5개 = 10점
같은 숫자 2개 + 같은 숫자 2개 = 3점
풀 하우스(같은 숫자 2개와 또 다른 같은숫자 3개, 예: 6,9,9,6,9) = 8점
7포함 스트레이트 (7이 있는 스트레이트, 예를들어 4,5,6,7,8) = 8점
7제외 스트레이트 (7이 없는 스트레이트, 예를들어 2,3,4,5,6 또는 8,9,10,11,12 ) = 12점
대각선으로 득점한 점수는 두 배의 점수를 얻습니다.
de7739585f20d6e5ef96d51c1db51395fcb79ace
Gamehelpkado
0
317
1659
2025-02-18T07:34:51Z
Ryu2180
10448
새 문서: 카드에는 세 가지 특성이 있습니다. 1~5까지의 숫자, 5가지의 리본 색, 5가지 선물종류. 플레이어는 차례대로 선물을 주는 사람이 되며, 주는 사람이 되면 카드를 뽑고 혼자 보고, 누군가 다른 사람이게 뒤집어서 줍니다. 카드를 받은 플레이어는 자신의 카드를 볼 수 있습니다. 모든 사람(자신 포함)에게 카드를 주고 나면, 왼쪽에 있는 플레이어와 당신이 선물을 교...
wikitext
text/x-wiki
카드에는 세 가지 특성이 있습니다.
1~5까지의 숫자, 5가지의 리본 색, 5가지 선물종류.
플레이어는 차례대로 선물을 주는 사람이 되며, 주는 사람이 되면 카드를 뽑고 혼자 보고, 누군가 다른 사람이게 뒤집어서 줍니다.
카드를 받은 플레이어는 자신의 카드를 볼 수 있습니다.
모든 사람(자신 포함)에게 카드를 주고 나면, 왼쪽에 있는 플레이어와 당신이 선물을 교환할 수 있습니다.
원한다면, 색깔과 사물을 말합니다.
만약 그 중 하나가 당신이 그 턴에 자신에게 준 선물과 일치하면, 당신은 카드를 교환해야 하고, 모든 사람이 자신의 카드를 전시구역에 추가합니다.
만약 그들이 당신의 선물 색깔이나 사물의 이름을 말하지 못하면, 다음 플레이어가 시도할 수 있습니다. (누군가가 색깔과 사물을 모두 맞히면, 그들은 게임이 끝날 때 2점 보너스로 뒤집힌 카드를 받습니다.)
12라운드가 끝나면 모든 사람이 3줄 높이, 4열 너비의 격자에 12장의 카드를 가지게 됩니다. 한 열의 모든 리본이 같은 색이면 해당 열에서 가장 높은 값과 같은 점수를 얻습니다. 각 행에서 해당 행의 객체를 선택한 다음 해당 객체를 보여주는 카드의 모든 값을 합산합니다.
3b7259e2a834bd0a40d0d4f4dde00b4cb961ef39
Gamehelpthirtyone
0
264
1660
1553
2025-02-25T03:06:06Z
Ufm
6353
wikitext
text/x-wiki
== 개요 ==
트럼프 카드를 사용하는 클래식 카드 게임이다.
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
3. 카드 더미에 카드가 부족할 경우 마지막 차례를 진행합니다.
== 점수 ==
누군가 31이나 불꽃을 완성하면 즉시 라운드가 종료됩니다.
동점일 경우 라운드 스톱을 선언한 사람이 점수가 더 높은 것으로 취급합니다. 그 외의 경우 무늬로 승패를 가립니다. (클로버> 스페이드 > 하트 > 다이아몬드 - 스카트의 무늬 순서와 동일)
2명 이상이 트리플일 경우, 더 높은 등급이 더 높은 것으로 취급합니다.
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
트리플은 30.5점, 불꽃(A 트리플)은 32점으로 취급합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다.
여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
34ec86e968306b0590c16cf885095204785bb9a3
1661
1660
2025-02-25T03:06:36Z
Ufm
6353
wikitext
text/x-wiki
== 개요 ==
트럼프 카드를 사용하는 클래식 카드 게임이다.
== 목표 ==
2개의 여벌 목숨을 가지며 최후까지 살아남으십시오.
== 진행 ==
1. 각자 3장의 카드를 받습니다. 플레이어들은 첫 턴에 자신의 3장을 모두 교체할지 그대로 가질지 선택합니다.
바닥에 3장이 깔려있다면 그 카드와 교체하고 그렇지 않다면 자신의 카드를 모두 바닥에 깔고 3장을 새로 뽑습니다. 모든 플레이어가 카드를 그대로 가져간다면 3장의 카드를 새로 뽑아 바닥에 놓습니다.
2. 플레이어는 매 턴마다 세가지 행동 중 하나를 선택해야 합니다.
1) 바닥에 있는 카드 한 장과 내 카드 한 장을 교환할 수 있습니다.
2) 차례를 넘깁니다. 모든 플레이어가 차례를 넘기면 새로 3장을 뽑아 바닥에 놓습니다. 기존 카드는 모두 버립니다.
3) 라운드 스톱(도중에 31을 완성하는 사람이 없다면 다른 모두가 마지막 차례를 진행합니다.)
3. 카드 더미에 카드가 부족할 경우 마지막 차례를 진행합니다.
== 점수 ==
누군가 31이나 불꽃을 완성하면 즉시 라운드가 종료됩니다.
그 외의 경우 무늬로 승패를 가립니다. (클로버 > 스페이드 > 하트 > 다이아몬드 - 스카트의 무늬 순서와 동일)
2명 이상이 트리플일 경우, 더 높은 등급이 더 높은 것으로 취급합니다.
=== 동일한 모양 ===
동일한 모양 숫자를 모두 더합니다. J, Q, K는 10으로 취급합니다. A는 11로 취급합니다. 31 완성시 이후의 모든 턴을 스킵하고 승리합니다.
=== 동일한 숫자 ===
트리플은 30.5점, 불꽃(A 트리플)은 32점으로 취급합니다.
== 승부 ==
라운드가 끝날 때, (라운드 승자를 제외하고) 20점 이하인 사람 모두와 21점 이상인 사람 중 패 점수가 가장 낮은 사람 모두가 목숨 1개씩을 잃습니다.
여벌의 목숨이 없는 상태에서 지면 게임에서 탈락합니다.
4fc39996b2e7bca8c5949734feab1a5a939792fb
Gamehelptheguildofmerchantexplorers
0
318
1662
2025-02-26T16:29:18Z
Jeho2681
10526
새 문서: >목표 게임의 목표는 가능한 한 많은 동전을 얻는 것입니다. 플레이어는 도시, 유적지 또는 발견 타워에 탐험가를 배치하여 동전을 얻습니다. 플레이어는 도시, 수도 또는 다른 마을 간에 무역로를 만들 수도 있습니다. >게임 플레이 게임은 4개의 시대로 구성되어 있습니다. 각 시대에 플레이어는 탐험 카드를 공개한 후 탐험 덱이 고갈될 때까지 동시에 턴을 진행합...
wikitext
text/x-wiki
>목표
게임의 목표는 가능한 한 많은 동전을 얻는 것입니다. 플레이어는 도시, 유적지 또는 발견 타워에 탐험가를 배치하여 동전을 얻습니다. 플레이어는 도시, 수도 또는 다른 마을 간에 무역로를 만들 수도 있습니다.
>게임 플레이
게임은 4개의 시대로 구성되어 있습니다. 각 시대에 플레이어는 탐험 카드를 공개한 후 탐험 덱이 고갈될 때까지 동시에 턴을 진행합니다.
>각 시대가 끝나면:
모든 탐험가(큐브)가 지도에서 제거됩니다. 마을, 무역소, 보물 토큰 및 발견 타워는 각 플레이어의 지도에 남습니다.
다음 시대의 탐험 카드가 탐험 덱에 추가됩니다.
게임은 4번째 시대가 끝나면 끝나고 가장 많은 동전을 가진 플레이어가 승리합니다
>공간
탐험할 수 있는 기본 지형은 4가지가 있습니다.
초원
사막
산
바다
>각 지형 공간은 5가지 유형 중 하나일 수 있습니다.
1.빈 공간
마을을 배치할 수 있는 빈 공간.
2.코인 공간
탐험하면 코인을 획득합니다.
3.유적 공간
특별한 바다 지형.탐험하면 보물 카드를 획득합니다.
4.도시 공간
도시 공간 2개를 연결하여 무역로를 만듭니다.
5.발견 공간
특별한 "야생" 지형.탐험하면 코인을 획득합니다.
>탐험자 배치
플레이어는 현재 공개된 탐험 카드에 따라 동시에 탐험자를 배치할 수 있습니다.
플레이어는 탐험자를 배치를 할 수 있는곳은 다음과 같습니다.
1.수도 공간
2.이전에 배치한 탐험가
3.플레이어 마을
4.마을 발견
한 시대에 지역을 완전히 탐험하여 새로운 마을을 발견합니다.
지역은 같은 지형의 타일이 연속적으로 모여 있는 그룹입니다.
지역을 처음으로 완전히 탐험했을 때, 그 지역의 빈 타일 중 하나에 있는 탐험가를 즉시 마을로 교체합니다.
그런 다음 현재 시대와 같은 동전을 획득합니다.
각 지역에는 마을이 하나만 있을 수 있습니다.
탐험가와 달리 각 시대가 시작될 때 마을은 제거되지 않습니다.
무역로 만들기
도시 공간 2개를 연결하면 무역로가 만들어집니다. 도시는 탐험가, 마을 및/또는 수도의 사슬로 연결될 수 있습니다.
무역로를 만들 때 두 도시의 가치를 곱하고 그 양의 동전을 얻습니다.
그런 다음 이 도시 중 하나를 무역소로 덮습니다. 이 도시는 더 이상 무역로의 일부가 될 수 없습니다.
발견 공간과 타워
발견 공간은 "야생" 지형으로, 모든 유형의 탐험 액션으로 탐험할 수 있습니다.
탐험하면 플레이어가 탐험한 다른 발견 공간의 수(6/8/10/14)에 따라 동전을 얻습니다.
그런 다음 타워로 공간을 덮습니다. 이 공간은 다시 점수를 얻을 수 없습니다.
f78002900fc94902d615e202dc00a85cc30238e8
Gamehelpseasaltpaper
0
319
1663
2025-02-28T00:44:08Z
Joki123
9915
새 문서: 게임 하나의 덱과 두개의 버림 더미를 가지고 하는 게임입니다. 각 플레이어는 손에 카드를 들고 자신의 앞에 플레이 영역을 확보합니다. 손에 있던 앞에 내려놓든 상관없이 점수를 획득합니다. 턴 구조 1. 뽑기 둘 중 하나의 행동 • 덱에서 2장의 카드를 뽑고, 하나는 갖고 하나는 두개의 버림 더미 중에 한 곳에 버린다. (비어있는 버림 더미가 있으면 그 곳에...
wikitext
text/x-wiki
게임
하나의 덱과 두개의 버림 더미를 가지고 하는 게임입니다.
각 플레이어는 손에 카드를 들고 자신의 앞에 플레이 영역을 확보합니다.
손에 있던 앞에 내려놓든 상관없이 점수를 획득합니다.
턴 구조
1. 뽑기
둘 중 하나의 행동
• 덱에서 2장의 카드를 뽑고, 하나는 갖고 하나는 두개의 버림 더미 중에 한 곳에 버린다. (비어있는 버림 더미가 있으면 그 곳에 버려야 합니다.)
• 버림 더미 중 한 곳의 제일 위 카드 하나를 뽑습니다.
2. 한쌍의 패
만약 손에 플레이 가능한 한 쌍의 패가 있다면, 한 쌍의 패를 내고 아래 효과를 발동시킬 수 있습니다.
• 한 쌍의 게 = 버림 더미 중 한 곳에서 카드를 뽑습니다. (상대방은 무엇을 가져오는지 볼 수 없습니다.)
• 한 쌍의 배 = 한 턴 더 진행합니다.
• 한 쌍의 물고기 = 덱에서 카드를 하나 뽑습니다.
• 상어 + 수영하는 사람 = 상대방의 손에서 랜덤으로 카드를 하나 가져옵니다.
3. 외치기
만약 손패와 앞에 내려놓은 카드의 점수가 7점 이상이면 아래 둘 중 하나의 행동을 할 수 있습니다.
• "STOP" = 즉시 라운드 종료, 각 플레이어는 자신의 점수만큼 획득합니다. (색상 보너스는 획득하지 못합니다.)
• "LAST CHANCE" = 모든 다른 플레이어들이 한 번씩 턴을 갖습니다. 이것은 가장 많은 점수를 경쟁하는 것 입니다. 아래 상황에 따라 점수를 획득합니다.
• "LAST CHANCE"를 외친 사람의 점수가 제일 큰 경우 (동점 포함), 카드의 점수와 색상 보너스도 같이 획득합니다. 다른 플레이어들은 그들의 색상 보너스만 획득합니다.
• 다른 플레이어가 점수를 이긴 경우, "LAST CHANCE"를 외친 사람은 색상 보너스만 받고 나머지 플레이어들은 그들의 카드 점수를 획득합니다.
(색상 보너스는 그들의 카드 중 가장 많이 가진 색상의 카드 수 입니다.)
특수 상황: 플레이어의 턴이 끝날 때 덱이 고갈되어 있으면, 그 즉시 점수 획득없이 라운드가 종료 됩니다.
게임 종료
2/3/4인 플레이에서 누군가 40/35/30점을 달성하면 게임이 종료되고, 가장 높은 점수를 획득한 사람이 승리합니다.
동점인 경우 마지막 라운드에 뒷 순서로 진행한 사람이 승리합니다.
4장의 인어 카드를 모으면 승리합니다.
카드 목록
종류 (written in small writing on the bottom left of the card in the help panel)
9 x Crab
8 x Boat
7 x Fish
5 x Shark + 5 x Swimmer
4 x Mermaid
6 x Shell
5 x Octopus
3 x Penguin
2 x Sailor (anchor icon)
1 x Lighthouse
1 x Shoal of fish
1 x Penguin Colony
1 x Captain
색상 (displayed in the colour helper)
9 x Dark Blue
9 x Light Blue
8 x Black
8 x Yellow
6 x Green
4 x White
4 x Purple
4 x Gray
3 x Light Orange
3 x Pink
1 x Orange
더 많은 소금 확장
5 새로운 카드 타입
JELLYFISH - Pair with a swimmer to immobilize your opponents.
LOBSTER - Play with a CRAB to take a card from the top five of the draw pile.
CRAB BASKET - Get 1 point per crab.
STARFISH - Combine with any duo to get 3 points but no card effects.
SEAHORSE - A wild card to add 1 more card to any collection.
bcc53b1a51803089477d66e1901db47407775650
Tips bandido
0
320
1664
2025-03-01T13:39:39Z
WWWAWFDAG
10534
새 문서: 길을 막으셈
wikitext
text/x-wiki
길을 막으셈
9eb828ac6bfec07a6153ea62c05fea5bd161466c
1666
1664
2025-03-13T03:06:03Z
Ufm
6353
Removed meaningless document
wikitext
text/x-wiki
da39a3ee5e6b4b0d3255bfef95601890afd80709
Gamehelpelpasogwt
0
321
1665
2025-03-05T11:08:00Z
Jeho2681
10526
새 문서: 19세기 말의 엘파소: 5개 철도 회사가 선시티를 철도망에 연결하여 가축 무역의 주요 허브로 만들었습니다. 당시 목장주 역할을 맡아 최고의 가축을 엘파소로 데려와 돈과 승리 포인트를 얻으세요. 목표에 더 가까이 다가가려면 카우보이, 건설업자, 엔지니어를 더 고용하세요. 중앙 디스플레이 위쪽 중앙 디스플레이의 특징은 다음과 같습니다. 다양한 건물과 빈...
wikitext
text/x-wiki
19세기 말의 엘파소: 5개 철도 회사가 선시티를 철도망에 연결하여 가축 무역의 주요 허브로 만들었습니다.
당시 목장주 역할을 맡아 최고의 가축을 엘파소로 데려와 돈과 승리 포인트를 얻으세요.
목표에 더 가까이 다가가려면 카우보이, 건설업자, 엔지니어를 더 고용하세요.
중앙 디스플레이
위쪽 중앙 디스플레이의 특징은 다음과 같습니다.
다양한 건물과 빈 공간이 있는 지도와 이를 연결하는 원형 트레일은 점선으로 나타납니다.
중앙에는 위에 숫자가 있고 아래에 보너스가 표시된 무역소와 오렌지색 심멘탈 가축 카드가 있으며, 몇 개가 남았는지 카운터가 있습니다.
지도 위에는 건물 F에서 기차 액션을 통해 액세스할 수 있는 2-3개의 액션이 있는 4개의 기차 카드가 있습니다.
기차 옆에는 보너스 타일(종 모양 아이콘)과 그 옆에 있는 3개의 뒤집힌 타일, 목표 타일(뿔 모양 아이콘)과 그 옆에 있는 3개의 뒤집힌 타일이 있습니다. 이것들은 건물 F에서 기차 액션을 통해 얻을 수 있습니다.
지도 오른쪽에는 6가지 유형의 건물이 있는 건물 디스플레이가 있습니다. 각 건물에는 몇 개가 남았는지 보여주는 카운터가 있습니다. 건물 비용에 대한 자세한 내용은 물음표 아이콘을 클릭하세요. 건물은 건물 E에 지을 수 있습니다.
건물 아래에는 4가지 유형의 소를 특징으로 하는 가축 시장이 있으며, 각 유형의 소가 몇 마리 남았는지도 보여줍니다. 각 가축 카드의 가격을 알려주는 물음표 아이콘을 주목하세요. 가축은 건물 D에서 구매할 수 있습니다.
마지막으로, 가축 시장 아래에는 4가지 유형의 일꾼과 각 유형의 소가 몇 마리 남았는지도 표시됩니다. 이들은 건물 B에서 고용할 수 있습니다.
개인 디스플레이
개인 놀이 공간 특징:
맨 위에는 카드 더미가 몇 장 들어 있는지 표시되어 있고, 소 카드(시작 시 4장)가 있습니다. 게임이 진행됨에 따라, 버리는 더미가 손 오른쪽에 표시됩니다.
그 아래 왼쪽에는 플레이어 보드가 있는데, 왼쪽에는 보조 액션 4개가 있고, 그 중 4개는 디스크로 덮여 있습니다. 가운데에는 잠금 해제할 수 있는 보너스 3개가 있고, 오른쪽에는 엘파소에서 사용할 수 있는 인증서 트랙이 있는데, 엘파소 액션 참조)입니다.
마지막으로 플레이어 보드 오른쪽에는 각 유형의 일꾼이 몇 명 있는지 표시됩니다. 일꾼은 맨 위에 보너스가 인쇄되어 있어 턴 중 언제든지 사용할 수 있습니다(상태 표시줄에 이를 상기시켜주는 버튼이 있습니다).
사이드 바의 플레이어 패널에는 다음이 표시됩니다.
실시간 스코어링이 활성화된 경우 사용자 이름 아래에 점수가 표시됩니다.
그 아래에는 현금, 목동 범위, 영구 인증서 수, 인증서 트랙의 가치, 그리고 보유한 교환 토큰 수가 있습니다.
보유한 목표 타일은 설정 및 훈련 액션을 참조하세요.
설정
설정의 일부로, 역순으로 플레이어는 공개된 목표 타일 중 하나를 선택하고, 이는 사이드 바의 플레이어 패널에 배치됩니다. 작은 아이콘이 어떤 목표를 달성했는지 보여줍니다(지금은 첫 번째로 취하는 목표에 대해 X가 표시됩니다).
당신의 차례
당신의 차례는 이동, 행동, 청소의 순서로 세 단계로 구성됩니다. 당신의 차례 중 언제든지, 당신은 인쇄된 보너스를 위해 플레이 영역에서 일꾼을 버리거나 교환 토큰을 사용하여 당신의 손을 개선할 수 있습니다. 이러한 옵션을 알려주는 상태 표시줄 오른쪽의 버튼을 주목하세요.
이동
첫 번째 차례에는 엘파소(B-G)를 제외한 시작 건물을 선택하기만 하면 됩니다. 나중에 목동의 범위 내에서 시계 방향으로 건물을 선택할 수 있으며, 시작 지점은 3입니다(사이드 바의 플레이어 패널 참조). 빈 공간은 계산되지 않습니다. 길이 갈라지면 게임에서 더 유리한 옵션을 고려합니다.
행동
이동 중에 선택한 건물의 행동을 수행합니다. 건물 행동 대신 보조 행동을 선택할 수 있습니다. 상대방의 건물에 도착하면(자세한 내용은 아래 건물 건설 참조) 보조 행동만 수행할 수 있습니다.
보조 액션
플레이어 보드의 왼쪽에는 4개의 보조 액션이 있습니다. 2개는 처음부터 사용할 수 있으며 개선할 수 있고, 나머지 2개는 먼저 잠금 해제해야 합니다. 일부 건물에서는 효과의 일부로 보조 액션을 수행할 수 있습니다(톱니바퀴 아이콘).
플레이어 보드의 왼쪽에 있는 4개의 보조 액션은 위에서 아래로 다음과 같습니다.
$1을 얻습니다. 잠금 해제된 경우 대신 $3을 얻습니다.
인증서 트랙에서 인증서 1개를 얻습니다(최대 4개).
카드 1장을 교환합니다(교환 토큰을 사용하는 것과 동일, 참조). 잠금 해제된 경우 두 번째로 교환할 수 있습니다.
손에서 카드 1장을 폐기합니다(즉, 영구적으로 게임에서 제거합니다). 이 액션의 잠금 해제 비용은 $3입니다.
건물 액션
다음은 일반적인 건물 작업 중 일부입니다. 이러한 모든 작업은 선택 사항이며 어떤 순서로든 수행할 수 있습니다. 의심스럽거나 여기에 작업이 나열되지 않은 경우 도구 설명이나 인쇄된 부록을 확인하세요.
소를 버리고 돈(B, D 및 E)을 얻음: 표시된 소 카드를 버리고 2달러를 얻습니다. 손에 소가 더 많더라도 작업당 1개만 버릴 수 있습니다.
일꾼 고용(B):
5달러를 지불하고 중앙 디스플레이에서 일꾼 유형을 선택합니다. 일꾼은 즉시 다른 일꾼과 함께 배치됩니다.
야생 일꾼(세 가지 유형 모두 표시)을 선택하는 경우 추가로 4달러를 지불해야 합니다.
추가로 8달러를 지불하면 두 번째 일꾼을 고용할 수 있지만 첫 번째 일꾼과 다른 일꾼을 선택해야 합니다.
건물 B에서만 5달러와 8달러를 지불해야 합니다. 다른 건물과 효과(예: 무역소 9)는 이 작업을 무료로 제공할 수 있습니다(야생 일꾼을 선택하는 경우 예외 - 항상 추가로 4달러가 듭니다).
각 노동자는 카드에 인쇄된 대로 2 또는 3 VP의 가치가 있습니다.
소 구매(D):
소 시장에서 소를 골라 표시된 비용을 지불합니다. 왼쪽에서 오른쪽으로 소의 비용은 $2/$4/$6/$8이며 노동자 구역에서 1/2/3/4 카우보이(및/또는 야생 노동자)를 버려야 합니다.
새로운 소는 버리는 더미에 놓입니다. 돈과 카우보이가 더 많더라도 액션당 소를 하나만 살 수 있습니다.
소는 카드에 인쇄된 대로 다양한 수의 VP의 가치가 있습니다.
건물 건설(E):
중앙 디스플레이에서 건물을 선택하고 표시된 비용을 지불합니다. 일정 금액의 돈을 지불하면 일꾼 구역에서 여러 명의 건설자(또는 야생 일꾼)를 버려야 합니다.
그런 다음 길을 따라 빈 공간을 선택하고 공간에 인쇄된 추가 비용이 있는 경우 지불합니다.
이미 지도에 건물이 있는 경우 두 건물 간의 차액을 지불하여 더 가치 있는 건물로 업그레이드할 수 있습니다. 그러면 새 건물이 이전 건물을 대체하고 이전 건물을 다시 건설할 수 있게 됩니다. 건물을 업그레이드할 때 공간에 인쇄된 비용을 다시 지불할 필요가 없습니다.
감당할 수 있는 건물은 무엇이든 건설할 수 있지만 각 플레이어는 지도에 최대 2개의 건물만 가질 수 있습니다. 건물이 2개 있으면 업그레이드할 수 있습니다.
각 건물은 건물에 인쇄된 대로 VP의 가치가 있습니다
기차 사용(F):
기차 카드를 골라 카드에 인쇄된 비용을 지불합니다.최대 $8까지 지불하고 작업자 영역에서 엔지니어(및/또는 야생 작업자)를 여러 개 버려야 합니다.
선택한 기차의 효과를 수행합니다.목표 또는 보너스 타일을 얻을 때, 공개된 타일을 하나 가져오거나 해당 스택에서 하나를 뽑을 수 있습니다.
목표 타일은 조건을 충족하면 게임이 끝날 때 점수를 얻습니다. 게임의 모든 구성 요소는 하나의 목표에만 할당할 수 있습니다.건물 요구 사항의 경우 건물 자체가 아닌 건물에 지불한 작업자 수를 "소비"합니다(즉, 두 개 이상의 목표를 완료할 수 있음).
보너스 타일은 일회성 보너스 또는 영구 효과를 제공합니다.영구 효과에는 영구 인증서(무한대 기호 포함)와 엘파소에서 중복된 가축 카드를 셀 수 있는 기능(자세한 내용은 해당 작업 참조)이 있습니다.
기타 건물 작업에는 다음이 포함됩니다.보조 작업(톱니바퀴 기호) 수행, 돈 또는 인증서 획득, 교환 토큰(때로는 비용이 발생), 가축 또는 보너스/목표 타일 획득; 목동을 길로 옮겨 다른 행동을 취합니다.
엘파소 행동
목동을 움직일 때는 엘파소를 지나갈 수 없습니다. 엘파소에서는 다음 순서대로 다음 행동을 수행해야 합니다.
$5와 버리는 더미에 놓인 Simmental 소 카드를 얻습니다. 지도에 있는 Simmental 소 더미가 비어 있는 경우, 엘파소를 처음 방문한 플레이어가 그 공간에 목동을 놓고 점수를 매기는 동안 VP 2점을 얻습니다. 이렇게 하면 게임이 종료되고 다른 모든 플레이어는 한 가지 행동을 더 수행합니다. 나중에 엘파소에 도착한 플레이어는 목동을 그 공간에 놓지 않습니다.
게임에서는 다른 모든 사람에게 손을 공개하고 번식 가치를 계산합니다. 즉, 손에 있는 소 카드의 맨 위에 있는 숫자를 더합니다. 각 유형의 소는 한 번만 기여합니다. 즉, 적절한 보너스 타일이 없는 한 중복은 무시됩니다.
게임에서는 또한 보유한 영구 인증서(무한대 기호 포함)를 추가하고 인증서 트랙에 있는 인증서 중 몇 개를 추가할지 묻습니다. 또한, 해당 근로자의 인쇄된 보너스 액션에 따라, 추가 인증서를 구매하기 위해 근로자 구역에서 건설자를 폐기할 수도 있습니다.
총합을 확인한 후, 같은 값이나 더 낮은 값을 가진 지도상의 거래소와 플레이어 보드의 디스크를 선택해야 하며, 디스크는 해당 공간에 배치됩니다. 해당 공간에 보너스 액션이 있는 경우, 이제 보너스 액션을 취합니다. 0, 12, 16 공간을 제외하고 공간당 최대 디스크를 하나만 가질 수 있습니다. 다른 플레이어의 디스크는 중요하지 않습니다. 플레이어 보드 중앙에서 디스크를 제거하려면 10 이상의 가치를 가진 거래소를 선택해야 합니다. 10 이상의 공간은 게임 종료 시 VP의 가치가 있습니다.
마지막으로, 손패는 버려집니다.
정리
턴이 끝나면 게임은 시작 시 4개였던 손패 한도까지 뽑습니다. 이번 턴에 사용하지 않은 카드는 손에 남습니다.
점수계산
게임이 끝나는 방식은 El Paso Actions, bullet point 1을 참조하세요. 다른 플레이어가 마지막 턴을 마친 후 플레이어는 다음과 같이 점수를 받습니다.
$5당 1 VP—마지막 턴에 다음 옵션이 있습니다.
지도에 타일을 건설하여 VP
디스크와 교역소를 건설하여 VP—각 디스크가 계산됩니다.
목동이 시멘탈 공간에 있는 경우 가축에서 VP + 2 VP
일꾼에서 VP
보너스 타일에서 VP
목표 타일에서 VP—경쟁 타일이 있는 경우 게임에서 자동으로 최상의 결과를 결정합니다. 각 구성 요소는 하나의 목표 타일에만 귀속될 수 있습니다. 목표 건설의 경우 건물 자체가 아닌 건물에 사용된 일꾼의 총계가 고려됩니다. 목표에 실패해도 VP를 잃지 않습니다.
7bd74a095a363ed0e50a9f4778bab20e066c891c
Gamehelpstalkexchange
0
322
1667
2025-03-15T18:32:28Z
Jeho2681
10526
새 문서: (Blue)*게임 개요. *(/Blue) 게임에는 5종류의 꽃이 있으며, 각 토큰이 25개씩 있습니다. 게임 시작시 각 개인판에 비공개로 12개씩 지급됩니다. 게임 종료시 각 꽃의 가치에 따라서 승점으로 계산됩니다. 하지만, *게임 끝날때 가치가 가장높은 꽃은 절반*으로 떨어진후에 계산됩니다. (Blue)*게임 진행. *(/Blue) 각 플레이어는 2번의 행동을 수행할수 있습니다. 1.꽃 심기...
wikitext
text/x-wiki
(Blue)*게임 개요. *(/Blue)
게임에는 5종류의 꽃이 있으며, 각 토큰이 25개씩 있습니다.
게임 시작시 각 개인판에 비공개로 12개씩 지급됩니다.
게임 종료시 각 꽃의 가치에 따라서 승점으로 계산됩니다.
하지만, *게임 끝날때 가치가 가장높은 꽃은 절반*으로 떨어진후에 계산됩니다.
(Blue)*게임 진행. *(/Blue)
각 플레이어는 2번의 행동을 수행할수 있습니다.
1.꽃 심기
2.꽃 교환하기
3.추가 행동하기 [턴당 1회, 총 3회까지 가능]
(Blue)*게임 종료조건. *(/Blue)
1.한종류의 꽃이 10 이상 가치가 될때.
2.수확한 꽃 토큰이 꽃 가치 토큰을 지나칠때
b8ea8efbcf44e1d9f763d5599ad8f05bee610179
1668
1667
2025-03-15T18:32:54Z
Jeho2681
10526
wikitext
text/x-wiki
(Blue)*게임 개요. *(/Blue)
게임에는 5종류의 꽃이 있으며, 각 토큰이 25개씩 있습니다.
게임 시작시 각 개인판에 비공개로 12개씩 지급됩니다.
게임 종료시 각 꽃의 가치에 따라서 승점으로 계산됩니다.
하지만, *게임 끝날때 가치가 가장높은 꽃은 절반*으로 떨어진후에 계산됩니다.
(Blue)*게임 진행. *(/Blue)
각 플레이어는 2번의 행동을 수행할수 있습니다.
1.꽃 심기
2.꽃 교환하기
3.추가 행동하기 [턴당 1회, 총 3회까지 가능]
(Blue)*게임 종료조건. *(/Blue)
1.한종류의 꽃이 10 이상 가치가 될때.
2.수확한 꽃 토큰이 꽃 가치 토큰을 지나칠때
49e5e5bf998f9f3e6a6da6fd021da0eab714599c
Gamehelpflipseven
0
323
1669
2025-03-17T19:07:25Z
Patciiboy
10577
새 문서: 게임 준비 덱 구성: 카드 덱은 숫자 카드와 액션 카드로 나누어집니다. 숫자 카드: 12부터 0까지, 각 숫자의 카드가 주어진 수만큼 들어 있습니다. 12 카드 12장 11 카드 11장 10 카드 10장 … 계속해서 1 카드 1장과 0 카드 1장까지 포함됩니다. 액션 카드: Flip Three: 세 장의 카드를 뒤집거나 교환하는 카드. Freeze: 다른 플레이어의 차례를 멈추게 하는 카드. Second Chance: 한 번...
wikitext
text/x-wiki
게임 준비
덱 구성: 카드 덱은 숫자 카드와 액션 카드로 나누어집니다.
숫자 카드: 12부터 0까지, 각 숫자의 카드가 주어진 수만큼 들어 있습니다.
12 카드 12장
11 카드 11장
10 카드 10장
… 계속해서 1 카드 1장과 0 카드 1장까지 포함됩니다.
액션 카드:
Flip Three: 세 장의 카드를 뒤집거나 교환하는 카드.
Freeze: 다른 플레이어의 차례를 멈추게 하는 카드.
Second Chance: 한 번 실패한 동작을 다시 시도할 수 있는 카드.
Score Modifier: 카드의 점수를 변경하는 카드.
게임 목표
게임의 목표는 가장 높은 점수를 얻는 것입니다. 점수는 숫자 카드의 합으로 계산됩니다.
라운드가 끝날 때까지 7개의 서로 다른 숫자 카드를 모으면 자동으로 라운드가 종료되고, 15점의 보너스가 주어집니다.
버스트: 이미 모은 카드와 같은 숫자를 뽑으면 그 플레이어는 라운드에서 제외되고 점수를 얻지 못합니다.
게임 진행 방법
1. 카드 분배
게임이 시작되면 각 플레이어에게 한 장의 카드가 분배됩니다.
만약 분배되는 카드가 액션 카드라면, 그 카드를 즉시 실행하고, 카드 분배를 잠시 멈춥니다.
2. Hit 또는 Stay 선택
각 플레이어는 차례대로 Hit(카드를 한 장 더 뽑기) 또는 Stay(현재 카드 상태 유지)를 선택합니다.
Hit을 선택하면 새로운 카드가 분배되고, 이 카드는 기존의 카드 라인에 추가됩니다. 이때 Score Modifier 카드가 있을 수 있습니다.
Stay를 선택하면 더 이상 카드를 뽑지 않고 현재 상태에서 점수를 계산하게 됩니다.
3. 버스트 규칙
만약 뽑은 카드가 이미 있는 숫자와 동일하다면, 그 플레이어는 버스트 상태가 되어 라운드에서 제외됩니다. 버스트된 플레이어는 점수를 얻지 못합니다.
4. 라운드 종료
라운드가 종료되는 두 가지 경우가 있습니다:
7개의 유니크 숫자 카드를 모은 플레이어가 있을 때, 즉시 라운드가 종료되고 15점의 보너스가 추가됩니다.
모든 플레이어가 버스트하거나 Stay를 선택하면 라운드가 종료됩니다.
5. 점수 계산
라운드 종료 후, 각 플레이어의 점수는 자신의 카드 값의 합으로 계산됩니다.
예를 들어, 12, 10, 6이 있다면 점수는 12 + 10 + 6 = 28점이 됩니다.
액션 카드가 영향을 미쳤다면, 해당 카드의 효과에 맞춰 점수가 달라질 수 있습니다.
6. 승리 조건
라운드가 종료된 후, 가장 높은 점수를 가진 플레이어가 승리합니다.
6b22289a7a958e333e52576998e49b54f0def1b0
1670
1669
2025-03-17T19:08:04Z
Patciiboy
10577
wikitext
text/x-wiki
게임 준비
덱 구성: 카드 덱은 숫자 카드와 액션 카드로 나누어집니다.
숫자 카드: 12부터 0까지, 각 숫자의 카드가 주어진 수만큼 들어 있습니다.
12 카드 12장
11 카드 11장
10 카드 10장
… 계속해서 1 카드 1장과 0 카드 1장까지 포함됩니다.
액션 카드:
Flip Three: 세 장의 카드를 뒤집거나 교환하는 카드.
Freeze: 다른 플레이어의 차례를 멈추게 하는 카드.
Second Chance: 한 번 실패한 동작을 다시 시도할 수 있는 카드.
Score Modifier: 카드의 점수를 변경하는 카드.
게임 목표
게임의 목표는 가장 높은 점수를 얻는 것입니다. 점수는 숫자 카드의 합으로 계산됩니다.
라운드가 끝날 때까지 7개의 서로 다른 숫자 카드를 모으면 자동으로 라운드가 종료되고, 15점의 보너스가 주어집니다.
버스트: 이미 모은 카드와 같은 숫자를 뽑으면 그 플레이어는 라운드에서 제외되고 점수를 얻지 못합니다.
게임 진행 방법
1. 카드 분배
게임이 시작되면 각 플레이어에게 한 장의 카드가 분배됩니다.
만약 분배되는 카드가 액션 카드라면, 그 카드를 즉시 실행하고, 카드 분배를 잠시 멈춥니다.
2. Hit 또는 Stay 선택
각 플레이어는 차례대로 Hit(카드를 한 장 더 뽑기) 또는 Stay(현재 카드 상태 유지)를 선택합니다.
Hit을 선택하면 새로운 카드가 분배되고, 이 카드는 기존의 카드 라인에 추가됩니다. 이때 Score Modifier 카드가 있을 수 있습니다.
Stay를 선택하면 더 이상 카드를 뽑지 않고 현재 상태에서 점수를 계산하게 됩니다.
3. 버스트 규칙
만약 뽑은 카드가 이미 있는 숫자와 동일하다면, 그 플레이어는 버스트 상태가 되어 라운드에서 제외됩니다. 버스트된 플레이어는 점수를 얻지 못합니다.
4. 라운드 종료
라운드가 종료되는 두 가지 경우가 있습니다:
7개의 유니크 숫자 카드를 모은 플레이어가 있을 때, 즉시 라운드가 종료되고 15점의 보너스가 추가됩니다.
모든 플레이어가 버스트하거나 Stay를 선택하면 라운드가 종료됩니다.
5. 점수 계산
라운드 종료 후, 각 플레이어의 점수는 자신의 카드 값의 합으로 계산됩니다.
예를 들어, 12, 10, 6이 있다면 점수는 12 + 10 + 6 = 28점이 됩니다.
액션 카드가 영향을 미쳤다면, 해당 카드의 효과에 맞춰 점수가 달라질 수 있습니다.
6. 승리 조건
라운드가 종료된 후, 가장 높은 점수를 가진 플레이어가 승리합니다.
0a94debab33690cc17165e3145d9286d1e05b997
1671
1670
2025-03-17T19:10:21Z
Patciiboy
10577
wikitext
text/x-wiki
'''게임 준비'''
덱 구성: 카드 덱은 숫자 카드와 액션 카드로 나누어집니다.
숫자 카드: 12부터 0까지, 각 숫자의 카드가 주어진 수만큼 들어 있습니다.
12 카드 12장
11 카드 11장
10 카드 10장
… 계속해서 1 카드 1장과 0 카드 1장까지 포함됩니다.
액션 카드:
Flip Three: 세 장의 카드를 뒤집거나 교환하는 카드.
Freeze: 다른 플레이어의 차례를 멈추게 하는 카드.
Second Chance: 한 번 실패한 동작을 다시 시도할 수 있는 카드.
Score Modifier: 카드의 점수를 변경하는 카드.
게임 목표
게임의 목표는 가장 높은 점수를 얻는 것입니다. 점수는 숫자 카드의 합으로 계산됩니다.
라운드가 끝날 때까지 7개의 서로 다른 숫자 카드를 모으면 자동으로 라운드가 종료되고, 15점의 보너스가 주어집니다.
버스트: 이미 모은 카드와 같은 숫자를 뽑으면 그 플레이어는 라운드에서 제외되고 점수를 얻지 못합니다.
'''게임 진행 방법'''
1. 카드 분배
게임이 시작되면 각 플레이어에게 한 장의 카드가 분배됩니다.
만약 분배되는 카드가 액션 카드라면, 그 카드를 즉시 실행하고, 카드 분배를 잠시 멈춥니다.
2. Hit 또는 Stay 선택
각 플레이어는 차례대로 Hit(카드를 한 장 더 뽑기) 또는 Stay(현재 카드 상태 유지)를 선택합니다.
Hit을 선택하면 새로운 카드가 분배되고, 이 카드는 기존의 카드 라인에 추가됩니다. 이때 Score Modifier 카드가 있을 수 있습니다.
Stay를 선택하면 더 이상 카드를 뽑지 않고 현재 상태에서 점수를 계산하게 됩니다.
3. 버스트 규칙
만약 뽑은 카드가 이미 있는 숫자와 동일하다면, 그 플레이어는 버스트 상태가 되어 라운드에서 제외됩니다. 버스트된 플레이어는 점수를 얻지 못합니다.
4. 라운드 종료
라운드가 종료되는 두 가지 경우가 있습니다:
7개의 유니크 숫자 카드를 모은 플레이어가 있을 때, 즉시 라운드가 종료되고 15점의 보너스가 추가됩니다.
모든 플레이어가 버스트하거나 Stay를 선택하면 라운드가 종료됩니다.
5. 점수 계산
라운드 종료 후, 각 플레이어의 점수는 자신의 카드 값의 합으로 계산됩니다.
예를 들어, 12, 10, 6이 있다면 점수는 12 + 10 + 6 = 28점이 됩니다.
액션 카드가 영향을 미쳤다면, 해당 카드의 효과에 맞춰 점수가 달라질 수 있습니다.
6. 승리 조건
라운드가 종료된 후, 가장 높은 점수를 가진 플레이어가 승리합니다.
a2103a3e5c8ef3da338657d16347323f856d9101
1672
1671
2025-03-17T19:11:06Z
Patciiboy
10577
wikitext
text/x-wiki
'''게임 준비'''
덱 구성: 카드 덱은 숫자 카드와 액션 카드로 나누어집니다.
숫자 카드: 12부터 0까지, 각 숫자의 카드가 주어진 수만큼 들어 있습니다.
12 카드 12장
11 카드 11장
10 카드 10장
… 계속해서 1 카드 1장과 0 카드 1장까지 포함됩니다.
액션 카드:
Flip Three: 세 장의 카드를 뒤집거나 교환하는 카드.
Freeze: 다른 플레이어의 차례를 멈추게 하는 카드.
Second Chance: 한 번 실패한 동작을 다시 시도할 수 있는 카드.
Score Modifier: 카드의 점수를 변경하는 카드.
게임 목표
게임의 목표는 가장 높은 점수를 얻는 것입니다. 점수는 숫자 카드의 합으로 계산됩니다.
라운드가 끝날 때까지 7개의 서로 다른 숫자 카드를 모으면 자동으로 라운드가 종료되고, 15점의 보너스가 주어집니다.
버스트: 이미 모은 카드와 같은 숫자를 뽑으면 그 플레이어는 라운드에서 제외되고 점수를 얻지 못합니다.
'''게임 진행 방법'''
1. 카드 분배
게임이 시작되면 각 플레이어에게 한 장의 카드가 분배됩니다.
만약 분배되는 카드가 액션 카드라면, 그 카드를 즉시 실행하고, 카드 분배를 잠시 멈춥니다.
2. Hit 또는 Stay 선택
각 플레이어는 차례대로 Hit(카드를 한 장 더 뽑기) 또는 Stay(현재 카드 상태 유지)를 선택합니다.
Hit을 선택하면 새로운 카드가 분배되고, 이 카드는 기존의 카드 라인에 추가됩니다. 이때 Score Modifier 카드가 있을 수 있습니다.
Stay를 선택하면 더 이상 카드를 뽑지 않고 현재 상태에서 점수를 계산하게 됩니다.
3. 버스트 규칙
만약 뽑은 카드가 이미 있는 숫자와 동일하다면, 그 플레이어는 버스트 상태가 되어 라운드에서 제외됩니다. 버스트된 플레이어는 점수를 얻지 못합니다.
4. 라운드 종료
라운드가 종료되는 두 가지 경우가 있습니다:
7개의 유니크 숫자 카드를 모은 플레이어가 있을 때, 즉시 라운드가 종료되고 15점의 보너스가 추가됩니다.
모든 플레이어가 버스트하거나 Stay를 선택하면 라운드가 종료됩니다.
5. 점수 계산
라운드 종료 후, 각 플레이어의 점수는 자신의 카드 값의 합으로 계산됩니다.
예를 들어, 12, 10, 6이 있다면 점수는 12 + 10 + 6 = 28점이 됩니다.
액션 카드가 영향을 미쳤다면, 해당 카드의 효과에 맞춰 점수가 달라질 수 있습니다.
6. 승리 조건
라운드가 종료된 후, 가장 높은 점수를 가진 플레이어가 승리합니다.
bcab9bd77d1b4893c48738403422e71cd6829229
1673
1672
2025-03-17T19:11:56Z
Patciiboy
10577
wikitext
text/x-wiki
'''게임 준비'''
덱 구성: 카드 덱은 숫자 카드와 액션 카드로 나누어집니다.
숫자 카드: 12부터 0까지, 각 숫자의 카드가 주어진 수만큼 들어 있습니다.
12 카드 12장
11 카드 11장
10 카드 10장
… 계속해서 1 카드 1장과 0 카드 1장까지 포함됩니다.
액션 카드:
Flip Three: 세 장의 카드를 뒤집거나 교환하는 카드.
Freeze: 다른 플레이어의 차례를 멈추게 하는 카드.
Second Chance: 한 번 실패한 동작을 다시 시도할 수 있는 카드.
Score Modifier: 카드의 점수를 변경하는 카드.
게임 목표
게임의 목표는 가장 높은 점수를 얻는 것입니다. 점수는 숫자 카드의 합으로 계산됩니다.
라운드가 끝날 때까지 7개의 서로 다른 숫자 카드를 모으면 자동으로 라운드가 종료되고, 15점의 보너스가 주어집니다.
버스트: 이미 모은 카드와 같은 숫자를 뽑으면 그 플레이어는 라운드에서 제외되고 점수를 얻지 못합니다.
'''게임 진행 방법'''
1. 카드 분배: 게임이 시작되면 각 플레이어에게 한 장의 카드가 분배됩니다.
만약 분배되는 카드가 액션 카드라면, 그 카드를 즉시 실행하고, 카드 분배를 잠시 멈춥니다.
2. Hit 또는 Stay 선택: 각 플레이어는 차례대로 Hit(카드를 한 장 더 뽑기) 또는 Stay(현재 카드 상태 유지)를 선택합니다.
Hit을 선택하면 새로운 카드가 분배되고, 이 카드는 기존의 카드 라인에 추가됩니다. 이때 Score Modifier 카드가 있을 수 있습니다.
Stay를 선택하면 더 이상 카드를 뽑지 않고 현재 상태에서 점수를 계산하게 됩니다.
3. 버스트 규칙: 만약 뽑은 카드가 이미 있는 숫자와 동일하다면, 그 플레이어는 버스트 상태가 되어 라운드에서 제외됩니다. 버스트된 플레이어는 점수를 얻지 못합니다.
4. 라운드 종료: 라운드가 종료되는 두 가지 경우가 있습니다:
7개의 유니크 숫자 카드를 모은 플레이어가 있을 때, 즉시 라운드가 종료되고 15점의 보너스가 추가됩니다.
모든 플레이어가 버스트하거나 Stay를 선택하면 라운드가 종료됩니다.
5. 점수 계산: 라운드 종료 후, 각 플레이어의 점수는 자신의 카드 값의 합으로 계산됩니다.
예를 들어, 12, 10, 6이 있다면 점수는 12 + 10 + 6 = 28점이 됩니다.
액션 카드가 영향을 미쳤다면, 해당 카드의 효과에 맞춰 점수가 달라질 수 있습니다.
6. 승리 조건: 라운드가 종료된 후, 가장 높은 점수를 가진 플레이어가 승리합니다.
187ddc38ed75c783461f60b23f35d453f33fe3ed
Gamehelpthewhitecastle
0
324
1674
2025-03-18T18:33:58Z
Patciiboy
10577
새 문서: 라운드 진행 플레이어들은 돌아가며 주사위를 배치하며, 각 플레이어가 3개의 주사위를 배치하면 라운드가 종료됩니다. 당신의 턴 턴은 다음 순서대로 진행됩니다. 1️⃣ 주사위 선택 • 다리(Bridge)의 양 끝 중 하나에서 주사위를 선택하고, 해당 주사위를 사용할 위치를 선택합니다. • 선택한 주사위의 숫자가 공간의 숫자보다 낮으면, 부족한 눈금 수만큼 동...
wikitext
text/x-wiki
라운드 진행
플레이어들은 돌아가며 주사위를 배치하며, 각 플레이어가 3개의 주사위를 배치하면 라운드가 종료됩니다.
당신의 턴
턴은 다음 순서대로 진행됩니다.
1️⃣ 주사위 선택
• 다리(Bridge)의 양 끝 중 하나에서 주사위를 선택하고, 해당 주사위를 사용할 위치를 선택합니다.
• 선택한 주사위의 숫자가 공간의 숫자보다 낮으면, 부족한 눈금 수만큼 동전(coin)을 지불해야 합니다.
• 선택한 주사위의 숫자가 공간의 숫자보다 높으면, 초과한 눈금 수만큼 동전을 받습니다.
• 다리의 왼쪽(더 낮은 숫자)의 주사위를 가져온 경우, 추가로 등불 액션(플레이어 보드 아래에 배치된 카드의 효과)을 사용할 수 있습니다.
2️⃣ 주사위의 메인 액션 수행
배치 가능 지역
🔹 성(Castle)
• 주사위는 성의 1층과 2층의 5개 공간 중 어디든 배치할 수 있습니다.
• 선택한 주사위의 색상과 일치하는 모든 액션을 수행합니다.
🔹 성벽 밖(Outside the Walls)
• 어떤 색상의 주사위든 배치할 수 있으며, 인접한 주요 액션(정원사, 궁정 관리인, 전사)을 수행합니다.
🔹 개인 영지(Personal Domain)
• 공개된 공간의 자원을 모두 얻고, 해당 줄에 있는 카드의 액션을 수행합니다.
주요 액션 (Principal Actions)
🌿 정원사(Gardener)
• 정원 카드 중 정원사가 없는 카드를 선택하고, 음식(Food) 비용을 지불해 카드를 배치 및 활성화합니다.
• 해당 카드는 라운드 종료 시 그 위에 주사위가 남아 있으면 다시 활성화됩니다.
👑 궁정 관리인(Courtier)
• 선택 1: 동전 2개를 지불하고 궁정 관리인을 궁전에 배치합니다.
• 선택 2: 진주 자원(Mother of Pearl) 2개 또는 5개를 사용해 궁정 관리인을 1~2층 위로 이동시킵니다.
• 궁정 관리인이 성의 최상층(3층)에 도달하면 보너스 공간에 배치하고 등불 보상(플레이어 보드 아래 카드)을 받습니다.
• 1층 또는 2층에서 멈춘 경우, 카드 한 장을 선택해 가져가고 라이트 배너(Light Banner) 액션을 수행한 후 카드를 뒤집어 미래 등불 액션으로 추가합니다.
⚔️ 무사(Warrior)
• 야드(Yard) 지역 중 하나를 선택하고, 철(Iron) 자원을 지불해 전사를 배치하고 보상을 받습니다.
• 게임 종료 시, 성에 있는 궁정 관리인의 수와 곱해 점수 배율이 결정됩니다.
다이묘 액션(Daimyo Actions)
• 다이묘 인장을 사용하여 자원을 2:1 비율로 교환하거나 동전을 1:1 비율로 교환할 수 있습니다.
라운드 종료 (End of Round)
1. 턴 순서 조정: 시간이 흐름(Passage of Time, 황새(Stork) 트랙)에서 가장 멀리 오른쪽에 있는 플레이어부터 순서 조정.
2. 다리 위 주사위 확인:
• 다리 위에 남아있는 주사위가 있다면 정원사들이 다시 활성화됩니다.
• 단, 마지막 라운드(3라운드 종료 후)에는 정원사가 다시 활성화되지 않습니다.
3. 라운드 진행:
• 게임은 3라운드 후 종료됩니다.
게임 종료 및 점수 계산 (End of Game Scoring)
1️⃣ 남은 자원 점수
• 동전과 다이묘 인장 5개당 1 클랜 포인트 (소수점 버림).
• 특정 자원을 3~6개 남겼다면 1 클랜 포인트, 7개 이상 남겼다면 2 클랜 포인트.
2️⃣ 시간의 흐름(Passage of Time) 점수
• 영향력 마커가 두 번째 시즌에 도달했다면 3 클랜 포인트.
• 세 번째 시즌이면 6 클랜 포인트.
• 네 번째 시즌에 도달했다면, 마커가 위치한 공간의 점수를 받음 (10~15 클랜 포인트).
3️⃣ 클랜 멤버 점수
🏯 성 안의 궁정 관리인 점수
• 문(Gate): 1점
• 1층(집사, Stewards): 3점
• 2층(외교관, Diplomats): 6점
• 3층(다이묘, Daimyo): 10점
⚔️ 훈련장(Training Yards)의 무사 점수
• 훈련장 내 무사 가치 × 성 안의 궁정 관리인 수 (문에 있는 관리인은 제외)
🌿 정원 점수
• 각 정원사는 그들이 있는 카드의 점수만큼 클랜 포인트를 부여.
승리 조건
• 가장 많은 클랜 포인트를 얻은 플레이어가 승리!
• 동점일 경우, 턴 순서에서 더 높은 플레이어가 승리!
867b8e3544d607193f5d46b14ac903999a908634
1675
1674
2025-03-18T18:43:35Z
Patciiboy
10577
wikitext
text/x-wiki
'''라운드 진행'''
플레이어들은 돌아가며 주사위를 배치하며, 각 플레이어가 3개의 주사위를 배치하면 라운드가 종료됩니다.
'''당신의 턴'''
턴은 다음 순서대로 진행됩니다.
1️⃣ 주사위 선택: 다리의 양 끝 중 하나에서 주사위를 선택하고, 해당 주사위를 사용할 위치를 선택합니다. 선택한 주사위의 숫자가 공간의 숫자보다 낮으면, 부족한 눈금 수만큼 동전을 지불해야 합니다. 선택한 주사위의 숫자가 공간의 숫자보다 높으면, 초과한 눈금 수만큼 동전을 받습니다. 다리의 왼쪽(더 낮은 숫자)의 주사위를 가져온 경우, 추가로 등불 액션(플레이어 보드 아래에 배치된 카드의 효과)을 사용할 수 있습니다.
2️⃣ 주사위의 메인 액션 수행
'''배치 가능 지역'''
🔹 성: 주사위는 성의 1층과 2층의 5개 공간 중 어디든 배치할 수 있습니다. 선택한 주사위의 색상과 일치하는 모든 액션을 수행합니다.
🔹 성벽 밖: 어떤 색상의 주사위든 배치할 수 있으며, 인접한 주요 액션(정원사, 궁정 관리인, 무사)을 수행합니다.
🔹 개인 영지: 공개된 공간의 자원을 모두 얻고, 해당 줄에 있는 카드의 액션을 수행합니다.
'''주요 액션'''
🌿 정원사: 정원 카드 중 정원사가 없는 카드를 선택하고, 음식(Food) 비용을 지불해 카드를 배치 및 활성화합니다. 해당 카드는 라운드 종료 시 그 위에 주사위가 남아 있으면 다시 활성화됩니다.
👑 궁정 관리인: 선택 1: 동전 2개를 지불하고 궁정 관리인을 궁전에 배치합니다.
선택 2: 진주 자원 2개 또는 5개를 사용해 궁정 관리인을 1~2층 위로 이동시킵니다. 궁정 관리인이 성의 최상층(3층)에 도달하면 보너스 공간에 배치하고 등불 보상(플레이어 보드 아래 카드)을 받습니다. 층 또는 2층에서 멈춘 경우, 카드 한 장을 선택해 가져가고 라이트 배너액션 을 수행한 후 카드를 뒤집어 미래 등불 액션으로 추가합니다.
⚔️ 무사: 훈련장 지역 중 하나를 선택하고, 철 자원을 지불해 전사를 배치하고 보상을 받습니다. 게임 종료 시, 성에 있는 궁정 관리인의 수와 곱해 점수 배율이 결정됩니다.
'''다이묘 액션:''' 다이묘 인장을 사용하여 자원을 2:1 비율로 교환하거나 동전을 1:1 비율로 교환할 수 있습니다.
'''라운드 종료'''
1.턴 순서 조정: 시간이 흐름(황새 트랙)에서 가장 멀리 오른쪽에 있는 플레이어부터 순서 조정.
2.다리 위 주사위 확인: 다리 위에 남아있는 주사위가 있다면 정원사들이 다시 활성화됩니다. 단, 마지막 라운드(3라운드 종료 후)에는 정원사가 다시 활성화되지 않습니다.
3.라운드 진행: 게임은 3라운드 후 종료됩니다.
'''게임 종료 및 점수 계산'''
1️⃣ 남은 자원 점수: 동전과 다이묘 인장 5개당 1 클랜 포인트 (소수점 버림). 특정 자원을 3~6개 남겼다면 1 클랜 포인트, 7개 이상 남겼다면 2 클랜 포인트.
2️⃣ 시간의 흐름 점수: 영향력 마커가 두 번째 시즌에 도달했다면 3 클랜 포인트. 세 번째 시즌이면 6 클랜 포인트. 네 번째 시즌에 도달했다면, 마커가 위치한 공간의 점수를 받음 (10~15 클랜 포인트).
3️⃣ 클랜 멤버 점수:
🏯성 안의 궁정 관리인 점수:문(Gate): 1점, 1층(집사, Stewards): 3점, 2층(외교관, Diplomats): 6점, 3층(다이묘, Daimyo): 10점
⚔️ 훈련장의 무사 점수: 훈련장 내 무사 가치 × 성 안의 궁정 관리인 수 (문에 있는 관리인은 제외)
🌿 정원 점수: 각 정원사는 그들이 있는 카드의 점수만큼 클랜 포인트를 부여.
승리 조건
• 가장 많은 클랜 포인트를 얻은 플레이어가 승리!
• 동점일 경우, 턴 순서에서 더 높은 플레이어가 승리!
8dcc813b2e2c245b693b50514c223121d133722b
Gamehelppotionsofazerland
0
325
1676
2025-03-19T05:10:09Z
Veryberry126
10582
새 문서: 플레이어는 물약을 구하러 마을에 온 방문객의 명령을 이행하여 명예를 얻습니다. 6라운드가 끝나면 게임이 끝납니다. 최종 포인트가 집계되고 가장 많은 명예를 가진 플레이어가 승리합니다! 게임 플레이는 6라운드로 진행되며, 각 라운드는 4개의 별도 단계로 나뉩니다. 1. 준비 단계 2. 우선 순위 타일 결정 3. 물약 마시기 4. 액션 실행 - 준비 단계 - 라운드...
wikitext
text/x-wiki
플레이어는 물약을 구하러 마을에 온 방문객의 명령을 이행하여 명예를 얻습니다.
6라운드가 끝나면 게임이 끝납니다.
최종 포인트가 집계되고 가장 많은 명예를 가진 플레이어가 승리합니다!
게임 플레이는 6라운드로 진행되며, 각 라운드는 4개의 별도 단계로 나뉩니다.
1. 준비 단계
2. 우선 순위 타일 결정
3. 물약 마시기
4. 액션 실행
- 준비 단계 -
라운드 보너스 토큰 공개 및 마켓에 이전 라운드에 남은 카드를 모두 제거하고 새로 채운다(1라운드 제외).
대기열에 있는 방문자 카드를 마을로 이동시킨다. 마을 안의 방문자 카드 수는 제한이 없다.
- 우선 순위 타일 결정 -
우선 순위 타일 결정 시, 플레이어가 우선시하고 싶어하는 액션은 숫자가 낮아야 하고, 플레이어가 덜 중요하게 생각하는 액션은 숫자가 높아야 합니다.
- 물약 마시기 -
보유한 물약을 마셔 현재 해당되는 학습단계 이하의 보상을 1개 골라 받는다.
- 액션 종류 -
채집(Forage): 주사위를 굴려 물약을 만드는 데 필요한 재료를 얻습니다.
학습(Study): 각 물약 유형에 대한 학습 레벨이 증가합니다. 얻은 학습은 물약 유형 간에 나눌 수 있습니다.
마켓(Market): 가능한 한 많은 마켓 카드를 구매하고 표시된 보상을 얻으세요. 구매한 카드는 준비 단계에 채워집니다.
물약제작(Brew): 재료를 지불하여 물약을 제작합니다. 각 물약 유형마다 필요한 재료의 양이 다릅니다.
달성(Fulfil): 물약과 교환하여 가능한 한 많은 방문자 카드를 충족합니다. 표시된 보상과 명예를 얻습니다.
9e9b033e86f2eaefed4cc0d07e1e3303dd6e1f14
Gamehelpcatan
0
233
1677
1410
2025-03-20T13:25:35Z
KS63
10588
13점 승리
wikitext
text/x-wiki
게임 목표
(다양한 건물과 개발 카드를 구매할 수 있도록 자원 카드를
최대한 얻으세요! 그러면 10점에 도달하는 첫번째 플레이어가
될 수 있습니다!)
게임 준비
(게임판에 랜덤으로 장소에 언덕(벽돌), 숲(목재), 산(광석), 들판(곡물), 목초지, 사막(얻을수 있는 자원 x)
으로 구성되어 있습니다.
사막을 제외한 각 지형에는 2~12개의 숫자가 있습니다
사막에는 도둑을 넣고 시작합니다 . 그 후
각 플레이어는 차례대로 원하는 자리에 마을을 넣고 도로를
건설합니다 차례대로 건설했으면 다시 역순으로 건설합니다.)
게임 시작
(자원 생산을위한 주사위 던지기 (필수) :
당신의 차례에서 두 주사위를 던져 합계를 계산합니다.
주사위 결과값이 나온 지형의 근처에 자신의 마을이 있으면
그 지형의 자원을 가져옵니다(단, 강도나 도둑이 있을경우 가져올 수 없습니다)
7이 나오면 아무도 자원을 얻지 않고 8 개 이상의 자원을 가진 플레이어는 절반을 버려야합니다. 강도(도둑)를 새로운 지형으로 이동하고 지형 옆에 마을이나 도시가 있는 플레이어로부터 임의의 자원을 하나 무조건 훔쳐야 합니다.
거래(선택사항): 자신의 차례동안 다른 플레이어들이랑 거래가 가능합니다.
또한 모든 플레이어는 같은 자원 카드 4장을 원하는 자원 1장과 교환할 수 있으며, 해상무역을 할라면 거기까지 도로를 건설한뒤 거기에 말하는 거래값으로 교환이 가능합니다.
건설카드와 마을구입(선택사항): 얻은 자원카드들로
구입 비용이 충족반 된다면 개발카드와 마을과 도로를 구입 할
수 있습니다
도로는 첫 번째 마을에 반드시 연결해야하며 도로는 벽돌1개,목재1개 가격이 듭니다
마을을 지을때도 기존마을과 연결하여 지어야하며 마을은
벽돌 1개 목재 1개 양1마리 곡물 1개 비용이 듭니다
마을은 도시로도 업그레이드가 가능하며 업그레이드 비용은
3개의 돌, 2개의 곡물로 가능합니다.
개발카드는 돌 1개 양 1개 곡물 1개로 구입가능하며
기사카드(도둑옮기기) , 자원창고(원하는 자원 2개가져오기)
, 도로건설등 다양하게 있으며 , 개발카드를 잘 사용할경우
특수 점수를 독점 흭득 가능합니다.
개발카드는 얻은 다음 바로 사용불가하며, 다음턴 주사위
굴리기전에 사용가능합니다.
득점 : 마을은 1점 , 도시는 2점 ,개발카드엔 1점의 승리카드가 있으며 (게임종료조건을 달성하기전까진 비공개)
기사 카드 최소 3장으로 가장 많이 쓴 사람이 기사독점카드(2점) 흭득하며 도로도 최고로 많이 지은 사람이(최소 5도로) 2점을 얻습니다 (카드 갯수가 다른플레이어와 중복일경우
먼저 얻은 사람이 계속 업적카드를 유지합니다)
게임 종료
게임 동안 승리 포인트가 13 이상인 경우 (승점카드 포함)플레이어가 나올경우 게임이 종료되며 그 사람의 승리가 됩니다.
7daeffdfa3362e3db7b5b56342ba11685e0b94f0
1683
1677
2025-03-23T03:18:06Z
KS63
10588
wikitext
text/x-wiki
게임 목표
(다양한 건물과 개발 카드를 구매할 수 있도록 자원 카드를
최대한 얻으세요! 그러면 10점에 도달하는 첫번째 플레이어가
될 수 있습니다!)
게임 준비
(게임판에 랜덤으로 장소에 언덕(벽돌), 숲(목재), 산(광석), 들판(곡물), 목초지, 사막(얻을수 있는 자원 x)
으로 구성되어 있습니다.
사막을 제외한 각 지형에는 2~12개의 숫자가 있습니다
사막에는 도둑을 넣고 시작합니다 . 그 후
각 플레이어는 차례대로 원하는 자리에 마을을 넣고 도로를
건설합니다 차례대로 건설했으면 다시 역순으로 건설합니다.)
게임 시작
(자원 생산을위한 주사위 던지기 (필수) :
당신의 차례에서 두 주사위를 던져 합계를 계산합니다.
주사위 결과값이 나온 지형의 근처에 자신의 마을이 있으면
그 지형의 자원을 가져옵니다(단, 강도나 도둑이 있을경우 가져올 수 없습니다)
7이 나오면 아무도 자원을 얻지 않고 8 개 이상의 자원을 가진 플레이어는 절반을 버려야합니다. 강도(도둑)를 새로운 지형으로 이동하고 지형 옆에 마을이나 도시가 있는 플레이어로부터 임의의 자원을 하나 무조건 훔쳐야 합니다.
거래(선택사항): 자신의 차례동안 다른 플레이어들이랑 거래가 가능합니다.
또한 모든 플레이어는 같은 자원 카드 4장을 원하는 자원 1장과 교환할 수 있으며, 해상무역을 할라면 거기까지 도로를 건설한뒤 거기에 말하는 거래값으로 교환이 가능합니다.
건설카드와 마을구입(선택사항): 얻은 자원카드들로
구입 비용이 충족반 된다면 개발카드와 마을과 도로를 구입 할
수 있습니다
도로는 첫 번째 마을에 반드시 연결해야하며 도로는 벽돌1개,목재1개 가격이 듭니다
마을을 지을때도 기존마을과 연결하여 지어야하며 마을은
벽돌 1개 목재 1개 양1마리 곡물 1개 비용이 듭니다
마을은 도시로도 업그레이드가 가능하며 업그레이드 비용은
3개의 돌, 2개의 곡물로 가능합니다.
개발카드는 돌 1개 양 1개 곡물 1개로 구입가능하며
기사카드(도둑옮기기) , 자원창고(원하는 자원 2개가져오기)
, 도로건설등 다양하게 있으며 , 개발카드를 잘 사용할경우
특수 점수를 독점 흭득 가능합니다.
개발카드는 얻은 다음 바로 사용불가하며, 다음턴 주사위
굴리기전에 사용가능합니다.
득점 : 마을은 1점 , 도시는 2점 ,개발카드엔 1점의 승리카드가 있으며 (게임종료조건을 달성하기전까진 비공개)
기사 카드 최소 3장으로 가장 많이 쓴 사람이 기사독점카드(2점) 흭득하며 도로도 최고로 많이 지은 사람이(최소 5도로) 2점을 얻습니다 (카드 갯수가 다른플레이어와 중복일경우
먼저 얻은 사람이 계속 업적카드를 유지합니다)
게임 종료
게임 동안 승리 포인트가 10(본판)/13(확장판) 이상인 경우 (승점카드 포함)플레이어가 나올경우 게임이 종료되며 그 사람의 승리가 됩니다.
a61c3385bba50b0be97a1a47a153714a5d02b177
Tips harmonies
0
326
1678
2025-03-21T08:12:21Z
Breeze J
10590
새 문서: ●초반 전략 -서로 어울리는 짝꿍 동물들을 찾아보세요! (예: 고슴도치와 멧돼지, 다람쥐와 오리, 알파카와 독수리처럼, 서식지가 비슷한 동물들을 함께 고려하세요.) -서식지 궁합이 좋은 동물들을 우선적으로 선택하세요. (함께 살기 좋은 환경을 만들어 시너지를 내는 것이 중요합니다.) ●중반 및 후반 전략 -다양한 서식지를 가진 동물들을 확보하세요! (물,...
wikitext
text/x-wiki
●초반 전략
-서로 어울리는 짝꿍 동물들을 찾아보세요! (예: 고슴도치와 멧돼지, 다람쥐와 오리, 알파카와 독수리처럼, 서식지가 비슷한 동물들을 함께 고려하세요.)
-서식지 궁합이 좋은 동물들을 우선적으로 선택하세요. (함께 살기 좋은 환경을 만들어 시너지를 내는 것이 중요합니다.)
●중반 및 후반 전략
-다양한 서식지를 가진 동물들을 확보하세요! (물, 들판, 나무, 산, 건물 등 가능한 모든 서식지를 아우르는 동물들을 모아두면, 어떤 상황에도 유연하게 대처할 수 있습니다.)
-손에 같은 서식지 동물 카드를 너무 많이 들고 있지 마세요! (카드 오른쪽 테두리 색상과 오른쪽 하단 아이콘을 보고 서식지를 확인하세요. 같은 서식지 동물만 잔뜩 들고 있으면 선택지가 좁아질 수 있습니다.)
-서식지 균형을 맞춰 다양한 선택지를 확보하는 것이 핵심입니다! (어떤 토큰이 나오든 대응할 수 있도록, 다양한 서식지의 동물들을 준비해두세요.)
●추가 팁
-'짝꿍' 동물들을 활용하면 초반에 유리하게 시작할 수 있어요!
-후반으로 갈수록 '다양성'이 승리의 열쇠입니다!
-카드 오른쪽 테두리 색상과 하단 아이콘을 잘 보고, 서식지 균형을 유지하세요!
-이 팁들을 활용해서 게임을 더욱 재미있고 전략적으로 즐기시길 바랍니다!
3316bd8b628aa24ed759d85d94feafad18384383
1681
1678
2025-03-22T11:52:53Z
Breeze J
10590
wikitext
text/x-wiki
●초반 전략
-서로 어울리는 짝꿍 동물들을 찾아보세요! (예: 고슴도치와 멧돼지, 다람쥐와 오리, 알파카와 독수리처럼, 서식지가 비슷한 동물들을 함께 고려하세요.)
-서식지 궁합이 좋은 동물들을 우선적으로 선택하세요. (함께 살기 좋은 환경을 만들어 시너지를 내는 것이 중요합니다.)
●중반 및 후반 전략
-다양한 서식지를 가진 동물들을 확보하세요! (물, 들판, 나무, 산, 건물 등 가능한 모든 서식지를 아우르는 동물들을 모아두면, 어떤 상황에도 유연하게 대처할 수 있습니다.)
-손에 같은 서식지 동물 카드를 너무 많이 들고 있지 마세요! (카드 오른쪽 테두리 색상과 오른쪽 하단 아이콘을 보고 서식지를 확인하세요. 같은 서식지 동물만 잔뜩 들고 있으면 선택지가 좁아질 수 있습니다.)
-서식지 균형을 맞춰 다양한 선택지를 확보하는 것이 핵심입니다! (어떤 토큰이 나오든 대응할 수 있도록, 다양한 서식지의 동물들을 준비해두세요.)
●추가 팁
-'짝꿍' 동물들을 활용하면 초반에 유리하게 시작할 수 있어요!
-후반으로 갈수록 '다양성'이 승리의 열쇠입니다!
-카드 오른쪽 테두리 색상과 하단 아이콘을 잘 보고, 서식지 균형을 유지하세요!
-이 팁들을 활용해서 게임을 더욱 재미있고 전략적으로 즐기시길 바랍니다!
Write by Breeze
7d8f6501c979ad46cc01550c9f92ece73188ec28
Gamehelplivingforestduel
0
327
1679
2025-03-22T11:23:10Z
Breeze J
10590
새 문서: 리빙 포레스트 듀얼에서 두 플레이어는 여름과 겨울의 정령이 되어 신성한 숲을 구하고 궁극적인 보호자로 인정받기 위해 경쟁합니다. 목표는 유사하지만, 오직 하나의 계절만이 영예를 차지할 것입니다. ◆게임 목표 다음 네 가지 승리 조건 중 하나를 먼저 달성하세요. -자신의 숲에 3x3 직사각형 모양의 수호수 카드 심기 -모집 라인에 자신의 계절 카드만 남...
wikitext
text/x-wiki
리빙 포레스트 듀얼에서 두 플레이어는 여름과 겨울의 정령이 되어 신성한 숲을 구하고 궁극적인 보호자로 인정받기 위해 경쟁합니다.
목표는 유사하지만, 오직 하나의 계절만이 영예를 차지할 것입니다.
◆게임 목표
다음 네 가지 승리 조건 중 하나를 먼저 달성하세요.
-자신의 숲에 3x3 직사각형 모양의 수호수 카드 심기
-모집 라인에 자신의 계절 카드만 남기기
-불 토큰 8개 모으기
-오니비 카드를 상대가 소유했을 때, 오니비 생명체를 상대방 쪽으로 이동시키기
◆게임 진행
플레이어들은 번갈아 가며 턴을 진행합니다. 각 턴마다 다음 옵션 중 하나를 선택합니다.
공용 뽑기 더미에서 수호 동물 카드 1장을 뽑아 공용 도움 라인에 추가
공용 도움 라인의 수호 동물 카드 1장에 행동 토큰 1개 사용
수호 동물 카드 뽑기:
공용 뽑기 더미에서 카드 1장을 뽑아 다음 세 개의 도움 라인 중 하나에 앞면이 보이도록 놓습니다.
중립 동물인 경우 공용 도움 라인에 놓습니다.
자신의 계절 동물인 경우 자신의 도움 라인에 놓습니다.
상대방의 계절 동물인 경우 상대방의 도움 라인에 놓습니다.
각 동물은 나중에 두 개의 행동 토큰 중 하나를 사용하여 사용할 수 있는 요소를 제공합니다.
주의하세요: 고독한 동물을 너무 많이 공개하면 불리할 수 있습니다. 고독한 상징이 3개 나타나면 행동 토큰을 잃게 되며, 이는 행동 능력을 크게 감소시킵니다.
◆행동 토큰 사용
수행하려는 행동에 해당하는 마지막 요소를 가리키도록 카드에 행동 토큰 1개를 놓습니다. 공용 도움 라인의 시작 부분 또는 해당 요소를 가리키는 마지막 행동 토큰부터 보이는 해당 유형의 모든 요소를 계산합니다.
가능한 행동:
수호 동물 1마리 이상 모집
불 토큰 1개 이상 수집하여 불 끄기
보호수 1그루 이상 심기
오니비를 상대방 쪽으로 이동
◆턴 종료
여름과 겨울 모두 2개의 행동 토큰을 모두 사용하면 턴이 종료됩니다.
정화 지역의 불 토큰 값을 합산합니다. 각 불 토큰의 값은 위치에 따라 결정됩니다. 그런 다음 물 값을 합산합니다. 정화 지역의 불 값이 물 값보다 엄격하게 높은지 확인합니다. 그렇다면 정화 지역에 있는 각 불 토큰에 대해 자신의 계절에 해당하는 불 바란 카드를 공용 버린 카드 더미에 추가합니다.
다음으로, 오니비 스탠디 양쪽의 카드에 불 토큰을 놓습니다.
2개의 행동 토큰을 다시 가져와 자신의 앞에 놓고, 도움 라인의 모든 카드와 플레이어 개인 라인의 카드를 공용 버린 카드 더미에 놓습니다.
666b8f4798876ad66616531a9beb83eadb3be874
1680
1679
2025-03-22T11:23:50Z
Breeze J
10590
wikitext
text/x-wiki
리빙 포레스트 듀얼에서 두 플레이어는 여름과 겨울의 정령이 되어 신성한 숲을 구하고 궁극적인 보호자로 인정받기 위해 경쟁합니다.
목표는 유사하지만, 오직 하나의 계절만이 영예를 차지할 것입니다.
◆게임 목표
다음 네 가지 승리 조건 중 하나를 먼저 달성하세요.
-자신의 숲에 3x3 직사각형 모양의 수호수 카드 심기
-모집 라인에 자신의 계절 카드만 남기기
-불 토큰 8개 모으기
-오니비 카드를 상대가 소유했을 때, 오니비 생명체를 상대방 쪽으로 이동시키기
◆게임 진행
플레이어들은 번갈아 가며 턴을 진행합니다. 각 턴마다 다음 옵션 중 하나를 선택합니다.
공용 뽑기 더미에서 수호 동물 카드 1장을 뽑아 공용 도움 라인에 추가
공용 도움 라인의 수호 동물 카드 1장에 행동 토큰 1개 사용
수호 동물 카드 뽑기:
공용 뽑기 더미에서 카드 1장을 뽑아 다음 세 개의 도움 라인 중 하나에 앞면이 보이도록 놓습니다.
중립 동물인 경우 공용 도움 라인에 놓습니다.
자신의 계절 동물인 경우 자신의 도움 라인에 놓습니다.
상대방의 계절 동물인 경우 상대방의 도움 라인에 놓습니다.
각 동물은 나중에 두 개의 행동 토큰 중 하나를 사용하여 사용할 수 있는 요소를 제공합니다.
주의하세요: 고독한 동물을 너무 많이 공개하면 불리할 수 있습니다. 고독한 상징이 3개 나타나면 행동 토큰을 잃게 되며, 이는 행동 능력을 크게 감소시킵니다.
◆행동 토큰 사용
수행하려는 행동에 해당하는 마지막 요소를 가리키도록 카드에 행동 토큰 1개를 놓습니다. 공용 도움 라인의 시작 부분 또는 해당 요소를 가리키는 마지막 행동 토큰부터 보이는 해당 유형의 모든 요소를 계산합니다.
가능한 행동:
수호 동물 1마리 이상 모집
불 토큰 1개 이상 수집하여 불 끄기
보호수 1그루 이상 심기
오니비를 상대방 쪽으로 이동
◆턴 종료
여름과 겨울 모두 2개의 행동 토큰을 모두 사용하면 턴이 종료됩니다.
정화 지역의 불 토큰 값을 합산합니다. 각 불 토큰의 값은 위치에 따라 결정됩니다. 그런 다음 물 값을 합산합니다. 정화 지역의 불 값이 물 값보다 엄격하게 높은지 확인합니다. 그렇다면 정화 지역에 있는 각 불 토큰에 대해 자신의 계절에 해당하는 불 바란 카드를 공용 버린 카드 더미에 추가합니다.
다음으로, 오니비 스탠디 양쪽의 카드에 불 토큰을 놓습니다.
2개의 행동 토큰을 다시 가져와 자신의 앞에 놓고, 도움 라인의 모든 카드와 플레이어 개인 라인의 카드를 공용 버린 카드 더미에 놓습니다.
by 기분좋은바람
a3304a29c2faf571f779bc5496e6bec70bc54263
Gamehelpharmonies
0
328
1682
2025-03-22T12:14:53Z
Breeze J
10590
새 문서: ◆게임 개요 풍경을 건설하고 동물들의 서식지를 만들어 가장 많은 점수를 얻는 사람이 승리합니다. 토큰 종류 및 수량: 파란색 23개, 회색 23개, 갈색 21개, 녹색 19개, 노란색 19개, 빨간색 15개. 자연의 정령 카드(확장옵션): 각 카드별 추가 점수 조건을 제공합니다. 게임시작 전 무작위로 2장의 정령 카드를 선택합니다. 정령카드 점수 조건은 카드에 설명되어 있습...
wikitext
text/x-wiki
◆게임 개요
풍경을 건설하고 동물들의 서식지를 만들어 가장 많은 점수를 얻는 사람이 승리합니다.
토큰 종류 및 수량: 파란색 23개, 회색 23개, 갈색 21개, 녹색 19개, 노란색 19개, 빨간색 15개.
자연의 정령 카드(확장옵션): 각 카드별 추가 점수 조건을 제공합니다. 게임시작 전 무작위로 2장의 정령 카드를 선택합니다.
정령카드 점수 조건은 카드에 설명되어 있습니다.
◆플레이어 턴 진행
1. 토큰 배치
-반드시 자신의 보드에 턴마다 3개의 토큰을 배치해야 합니다.
(빈 공간에는 언제나 배치할 수 있습니다. 이전에 배치된 토큰 1개 또는 2개 위에 놓아 나무, 건물 또는 산을 만들 수 있습니다
-다른 토큰 아래에 놓거나 큐브 위에 놓을 수 없습니다.
2. 동물 카드 획득 및 큐브 배치
-동물 카드 1장을 가져와 자신의 보드 4개 카드 슬롯 중 하나에 놓습니다.
-각 동물 카드에는 서식지 패턴이 있습니다. 동물 카드에서 큐브를 가져와 해당 토큰의 패턴을 충족할 수 있습니다.
-토큰 하나에 큐브를 2개 이상 놓을 수 없습니다.
-사용 가능한 패턴에 따라 무제한으로 큐브를 놓을 수 있습니다.
-동물 카드의 모든 큐브가 배치되면 4개 카드 제한에 더 이상 포함되지 않습니다.
◆게임 종료
-보드에 채울 토큰이 더 이상 없거나 플레이어 중 누구라도 자신의 보드에 빈 공간이 2개 이하인 경우, 라운드를 완료하고 점수를 계산합니다.
◆점수 계산
나무(Tree): 갈색 토큰 0/1/2개 위에 녹색 토큰 1개 배치 시 각각 1/3/7점.
산(Mountain): 회색 토큰 1/2/3개 스택 시 각각 1/3/7점. (다른 산과 인접한 산만 점수를 얻습니다.)
밭(Field): 연속된 노란색 토큰 2개 이상 그룹당 5점.
건물(Building): 다른 토큰 위에 빨간색 토큰 1개 배치 시 인접한 3개 이상의 토큰이 서로 다른 색상일 경우 각 건물당 5점. (인접한 각 위치의 상단 토큰만 고려)
물(Water) (A면): 파란색 토큰으로 가장 긴 연속된 체인 점수. 임의의 파란색 토큰 2개를 선택하고 최단 경로로 연결된 파란색 토큰 수를 계산합니다.
(체인 양쪽 끝의 선택된 토큰 2개 포함) 2/3/4/5/6개 체인에 대해 각각 2/5/8/11/15점, 체인의 추가 토큰당 4점. 루프를 만드는 것은 최단 경로 규칙에 따라 강 길이 점수가 토큰 수의 절반 + 1이 되므로 권장되지 않습니다.
물(Water) (B면): 파란색 토큰으로 분리된 영역 점수. 파란색 토큰으로 분리된 각 섬마다 5점.
동물 카드: 큐브가 없는 최상단 공간에 표시된 숫자만큼 점수를 얻습니다. (카드에 큐브가 모두 있는 경우 0점)
Write by Breeze
f283d72de8f8127d401b56d8f8980c2d94ca6a77